WingMan – Blame information for rev 32

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