WingMan – Blame information for rev 8

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