WingMan – Blame information for rev 12

Subversion Repositories:
Rev:
Rev Author Line No. Line
8 office 1 using System;
2 using System.IO;
12 office 3 using System.Linq;
8 office 4 using System.Security.Cryptography;
5 using System.Text;
12 office 6 using System.Threading.Tasks;
8 office 7  
8 namespace WingMan.Utilities
9 {
10 public static class AES
11 {
12 office 12 private const int AesKeyIterations = 4096;
8 office 13 private const int AesBlockSize = 128;
14 private const CipherMode AesCipherMode = CipherMode.CBC;
15 private const PaddingMode AesPaddingMode = PaddingMode.PKCS7;
16 private const int AesKeySaltBytes = 16;
17 private static readonly RNGCryptoServiceProvider Rng = new RNGCryptoServiceProvider();
18  
19 ///////////////////////////////////////////////////////////////////////////
20 // Copyright (C) Wizardry and Steamworks 2016 - License: GNU GPLv3 //
21 ///////////////////////////////////////////////////////////////////////////
22 /// <summary>
23 /// Encrypts a string given a key and initialization vector.
24 /// </summary>
25 /// <param name="data">the string to encrypt</param>
26 /// <param name="key">the encryption key</param>
27 /// <param name="separator">the separator to use between the cyphertext and the IV</param>
28 /// <returns>Base64 encoded encrypted data</returns>
12 office 29 public static async Task<byte[]> Encrypt(byte[] data, string key, string separator = ":")
8 office 30 {
31 using (var rijdanelManaged = new RijndaelManaged())
32 {
33 // FIPS-197 / CBC
34 rijdanelManaged.BlockSize = AesBlockSize;
35 rijdanelManaged.Mode = AesCipherMode;
36 rijdanelManaged.Padding = AesPaddingMode;
37  
38 // Compute the salt and the IV from the key.
39 var salt = new byte[AesKeySaltBytes];
40 Rng.GetBytes(salt);
12 office 41 var derivedKey = new Rfc2898DeriveBytes(key, salt, AesKeyIterations);
42 rijdanelManaged.Key = derivedKey.GetBytes(rijdanelManaged.KeySize / 8);
43 rijdanelManaged.IV = derivedKey.GetBytes(rijdanelManaged.BlockSize / 8);
44  
45 using (var encryptor = rijdanelManaged.CreateEncryptor(rijdanelManaged.Key, rijdanelManaged.IV))
10 office 46 {
12 office 47 using (var memoryStream = new MemoryStream())
8 office 48 {
12 office 49 using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
8 office 50 {
12 office 51 using (var inputStream = new MemoryStream(data))
8 office 52 {
12 office 53 await inputStream.CopyToAsync(cryptoStream);
54 cryptoStream.FlushFinalBlock();
8 office 55  
12 office 56 inputStream.Position = 0L;
8 office 57  
12 office 58 return salt.Concat(memoryStream.ToArray()).ToArray();
8 office 59 }
60 }
61 }
62 }
63 }
64 }
65  
66 ///////////////////////////////////////////////////////////////////////////
67 // Copyright (C) Wizardry and Steamworks 2016 - License: GNU GPLv3 //
68 ///////////////////////////////////////////////////////////////////////////
69 /// <summary>
70 /// Decrypts a Base64 encoded string using AES with a given key and initialization vector.
71 /// </summary>
72 /// <param name="data">
73 /// a string consisting of the cyphertext to decrypt in Base64 and the IV in Base64 separated by the
74 /// separator
75 /// </param>
76 /// <param name="key">the encryption key</param>
77 /// <param name="separator">the separator to use between the cyphertext and the IV</param>
78 /// <returns>the decrypted data</returns>
12 office 79 public static async Task<byte[]> Decrypt(byte[] data, string key, string separator = ":")
8 office 80 {
12 office 81 var salt = data.Take(AesKeySaltBytes).ToArray();
82 var text = data.Skip(AesKeySaltBytes).ToArray();
8 office 83  
84 using (var rijdanelManaged = new RijndaelManaged())
85 {
86 // FIPS-197 / CBC
87 rijdanelManaged.BlockSize = AesBlockSize;
88 rijdanelManaged.Mode = AesCipherMode;
89 rijdanelManaged.Padding = AesPaddingMode;
90  
91 // Retrieve the key and the IV from the salt.
12 office 92 var derivedKey = new Rfc2898DeriveBytes(key, salt, AesKeyIterations);
93 rijdanelManaged.Key = derivedKey.GetBytes(rijdanelManaged.KeySize / 8);
94 rijdanelManaged.IV = derivedKey.GetBytes(rijdanelManaged.BlockSize / 8);
95  
96 using (var decryptor = rijdanelManaged.CreateDecryptor(rijdanelManaged.Key, rijdanelManaged.IV))
10 office 97 {
12 office 98 using (var memoryStream = new MemoryStream(text))
8 office 99 {
12 office 100 using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
8 office 101 {
12 office 102 using (var outputStream = new MemoryStream())
8 office 103 {
12 office 104 await cryptoStream.CopyToAsync(outputStream);
105  
106 outputStream.Position = 0L;
107  
108 return outputStream.ToArray();
8 office 109 }
110 }
111 }
112 }
113 }
114 }
115  
10 office 116 public static string ExpandKey(string password, int size = 32)
8 office 117 {
118 var sb = new StringBuilder(password);
119 do
120 {
121 sb.Append(password);
122 } while (sb.Length < size);
123  
124 return sb.ToString(0, size);
125 }
126 }
127 }