WingMan – Blame information for rev 34

Subversion Repositories:
Rev:
Rev Author Line No. Line
14 office 1 using System.IO;
12 office 2 using System.Linq;
8 office 3 using System.Security.Cryptography;
4 using System.Text;
12 office 5 using System.Threading.Tasks;
8 office 6  
7 namespace WingMan.Utilities
8 {
9 public static class AES
10 {
12 office 11 private const int AesKeyIterations = 4096;
8 office 12 private const int AesBlockSize = 128;
13 private const CipherMode AesCipherMode = CipherMode.CBC;
14 private const PaddingMode AesPaddingMode = PaddingMode.PKCS7;
15 private const int AesKeySaltBytes = 16;
16 private static readonly RNGCryptoServiceProvider Rng = new RNGCryptoServiceProvider();
17  
18 ///////////////////////////////////////////////////////////////////////////
19 // Copyright (C) Wizardry and Steamworks 2016 - License: GNU GPLv3 //
20 ///////////////////////////////////////////////////////////////////////////
21 /// <summary>
34 office 22 /// Encrypts an input stream given a key and initialization vector.
8 office 23 /// </summary>
34 office 24 /// <param name="inputStream">the stream to encrypt</param>
8 office 25 /// <param name="key">the encryption key</param>
34 office 26 /// <returns>an encrypted stream containing the salt and the data</returns>
27 public static async Task<MemoryStream> Encrypt(Stream inputStream, string key)
8 office 28 {
34 office 29 var outputStream = new MemoryStream();
30  
8 office 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 {
34 office 51 await inputStream.CopyToAsync(cryptoStream);
52 cryptoStream.FlushFinalBlock();
53  
54 memoryStream.Position = 0L;
55  
56 await outputStream.WriteAsync(salt, 0, AesKeySaltBytes);
57 await memoryStream.CopyToAsync(outputStream);
58  
59 outputStream.Position = 0L;
60  
61 return outputStream;
62 }
63 }
64 }
65 }
66 }
67  
68 ///////////////////////////////////////////////////////////////////////////
69 // Copyright (C) Wizardry and Steamworks 2016 - License: GNU GPLv3 //
70 ///////////////////////////////////////////////////////////////////////////
71 /// <summary>
72 /// Encrypts a byte array given a key and initialization vector.
73 /// </summary>
74 /// <param name="data">the byte array to encrypt</param>
75 /// <param name="key">the encryption key</param>
76 /// <returns>an encrypted byte array</returns>
77 public static async Task<byte[]> Encrypt(byte[] data, string key)
78 {
79 using (var rijdanelManaged = new RijndaelManaged())
80 {
81 // FIPS-197 / CBC
82 rijdanelManaged.BlockSize = AesBlockSize;
83 rijdanelManaged.Mode = AesCipherMode;
84 rijdanelManaged.Padding = AesPaddingMode;
85  
86 // Compute the salt and the IV from the key.
87 var salt = new byte[AesKeySaltBytes];
88 Rng.GetBytes(salt);
89 var derivedKey = new Rfc2898DeriveBytes(key, salt, AesKeyIterations);
90 rijdanelManaged.Key = derivedKey.GetBytes(rijdanelManaged.KeySize / 8);
91 rijdanelManaged.IV = derivedKey.GetBytes(rijdanelManaged.BlockSize / 8);
92  
93 using (var encryptor = rijdanelManaged.CreateEncryptor(rijdanelManaged.Key, rijdanelManaged.IV))
94 {
95 using (var memoryStream = new MemoryStream())
96 {
97 using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
98 {
12 office 99 using (var inputStream = new MemoryStream(data))
8 office 100 {
12 office 101 await inputStream.CopyToAsync(cryptoStream);
102 cryptoStream.FlushFinalBlock();
8 office 103  
34 office 104 memoryStream.Position = 0L;
8 office 105  
12 office 106 return salt.Concat(memoryStream.ToArray()).ToArray();
8 office 107 }
108 }
109 }
110 }
111 }
112 }
113  
114 ///////////////////////////////////////////////////////////////////////////
115 // Copyright (C) Wizardry and Steamworks 2016 - License: GNU GPLv3 //
116 ///////////////////////////////////////////////////////////////////////////
117 /// <summary>
34 office 118 /// Decrypts a byte array using a salt and a key.
8 office 119 /// </summary>
34 office 120 /// <param name="inputStream">a salt and data stream to decrypt</param>
8 office 121 /// <param name="key">the encryption key</param>
34 office 122 /// <returns>a memory stream containing the decrypted data</returns>
123 public static async Task<MemoryStream> Decrypt(Stream inputStream, string key)
8 office 124 {
34 office 125 var outputStream = new MemoryStream();
126  
127 var salt = new byte[AesKeySaltBytes];
128 await inputStream.ReadAsync(salt, 0, AesKeySaltBytes);
129  
130 var text = new byte[inputStream.Length - AesKeySaltBytes];
131 await inputStream.ReadAsync(text, 0, (int) (inputStream.Length - AesKeySaltBytes));
132  
133 //var salt = data.Take(AesKeySaltBytes).ToArray();
134 //var text = data.Skip(AesKeySaltBytes).ToArray();
135  
136 using (var rijdanelManaged = new RijndaelManaged())
137 {
138 // FIPS-197 / CBC
139 rijdanelManaged.BlockSize = AesBlockSize;
140 rijdanelManaged.Mode = AesCipherMode;
141 rijdanelManaged.Padding = AesPaddingMode;
142  
143 // Retrieve the key and the IV from the salt.
144 var derivedKey = new Rfc2898DeriveBytes(key, salt, AesKeyIterations);
145 rijdanelManaged.Key = derivedKey.GetBytes(rijdanelManaged.KeySize / 8);
146 rijdanelManaged.IV = derivedKey.GetBytes(rijdanelManaged.BlockSize / 8);
147  
148 using (var decryptor = rijdanelManaged.CreateDecryptor(rijdanelManaged.Key, rijdanelManaged.IV))
149 {
150 using (var memoryStream = new MemoryStream(text))
151 {
152 using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
153 {
154 await cryptoStream.CopyToAsync(outputStream);
155  
156 outputStream.Position = 0L;
157  
158 return outputStream;
159 }
160 }
161 }
162 }
163 }
164  
165 ///////////////////////////////////////////////////////////////////////////
166 // Copyright (C) Wizardry and Steamworks 2016 - License: GNU GPLv3 //
167 ///////////////////////////////////////////////////////////////////////////
168 /// <summary>
169 /// Decrypts a byte array using a salt and a key.
170 /// </summary>
171 /// <param name="data">a salt and data byte array to decrypt</param>
172 /// <param name="key">the encryption key</param>
173 /// <returns>a byte array containing the decrypted data</returns>
174 public static async Task<byte[]> Decrypt(byte[] data, string key)
175 {
12 office 176 var salt = data.Take(AesKeySaltBytes).ToArray();
177 var text = data.Skip(AesKeySaltBytes).ToArray();
8 office 178  
179 using (var rijdanelManaged = new RijndaelManaged())
180 {
181 // FIPS-197 / CBC
182 rijdanelManaged.BlockSize = AesBlockSize;
183 rijdanelManaged.Mode = AesCipherMode;
184 rijdanelManaged.Padding = AesPaddingMode;
185  
186 // Retrieve the key and the IV from the salt.
12 office 187 var derivedKey = new Rfc2898DeriveBytes(key, salt, AesKeyIterations);
188 rijdanelManaged.Key = derivedKey.GetBytes(rijdanelManaged.KeySize / 8);
189 rijdanelManaged.IV = derivedKey.GetBytes(rijdanelManaged.BlockSize / 8);
190  
191 using (var decryptor = rijdanelManaged.CreateDecryptor(rijdanelManaged.Key, rijdanelManaged.IV))
10 office 192 {
12 office 193 using (var memoryStream = new MemoryStream(text))
8 office 194 {
12 office 195 using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
8 office 196 {
12 office 197 using (var outputStream = new MemoryStream())
8 office 198 {
12 office 199 await cryptoStream.CopyToAsync(outputStream);
200  
201 outputStream.Position = 0L;
202  
203 return outputStream.ToArray();
8 office 204 }
205 }
206 }
207 }
208 }
209 }
210  
10 office 211 public static string ExpandKey(string password, int size = 32)
8 office 212 {
213 var sb = new StringBuilder(password);
214 do
215 {
216 sb.Append(password);
217 } while (sb.Length < size);
218  
219 return sb.ToString(0, size);
220 }
221 }
34 office 222 }