WingMan – Blame information for rev 36

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