|
3 | 3 | // See LICENSE file in the project root for full license information. |
4 | 4 | // |
5 | 5 |
|
6 | | -using System; |
| 6 | +using System.Runtime.CompilerServices; |
7 | 7 |
|
8 | 8 | namespace System.Security.Cryptography |
9 | 9 | { |
10 | 10 | /// <summary> |
11 | | - /// Specifies the block cipher mode to use for encryption. |
| 11 | + /// Provides an Advanced Encryption Standard (AES) algorithm to encrypt and decrypt data. |
12 | 12 | /// </summary> |
13 | | - public enum CipherMode |
| 13 | + public class Aes |
14 | 14 | { |
15 | | - /// <summary> |
16 | | - /// The Electronic Codebook (ECB) mode encrypts each block individually. Any blocks |
17 | | - /// of plain text that are identical and in the same message, or that are in a different |
18 | | - /// message encrypted with the same key, will be transformed into identical cipher |
19 | | - /// text blocks. Important: This mode is not recommended because it opens the door |
20 | | - /// for multiple security exploits. If the plain text to be encrypted contains substantial |
21 | | - /// repetition, it is feasible for the cipher text to be broken one block at a time. |
22 | | - /// It is also possible to use block analysis to determine the encryption key. Also, |
23 | | - /// an active adversary can substitute and exchange individual blocks without detection, |
24 | | - /// which allows blocks to be saved and inserted into the stream at other points |
25 | | - /// without detection. |
26 | | - /// </summary> |
27 | | - ECB = 2 |
28 | | - } |
| 15 | + private CipherMode _mode; |
| 16 | + private byte[] _key; |
29 | 17 |
|
30 | | - /// <summary> |
31 | | - /// Encryption Standard (AES) |
32 | | - /// </summary> |
33 | | - public class AES |
34 | | - { |
35 | 18 | /// <summary> |
36 | 19 | /// Gets or sets the mode for operation of the symmetric algorithm. |
37 | 20 | /// </summary> |
38 | | - /// <returns>The mode for operation of the symmetric algorithm. The default is System.Security.Cryptography.CipherMode.ECB.</returns> |
39 | | - public virtual CipherMode Mode { get; set; } = CipherMode.ECB; |
40 | | - |
41 | | - /// <summary> |
42 | | - /// Initializes a new instance of the System.Security.Cryptography.Aes class. |
43 | | - /// </summary> |
44 | | - public AES() |
45 | | - { |
46 | | - |
47 | | - } |
48 | | - /// <summary> |
49 | | - /// Encrypt the array of bytes. |
50 | | - /// </summary> |
51 | | - /// <param name="key">The secret key to use for the symmetric algorithm.</param> |
52 | | - /// <param name="data">The array of byte for encryption</param> |
53 | | - /// <returns>The encrypted array of bytes</returns> |
54 | | - public byte[] Encrypt(byte[] key, byte[] data) |
55 | | - { |
56 | | - byte[] buf = null; |
57 | | - |
58 | | - if (Mode == CipherMode.ECB) |
59 | | - { |
60 | | - buf = EncryptAesEcb(key, data); |
61 | | - } |
62 | | - |
63 | | - return buf; |
64 | | - } |
| 21 | + /// <value>The mode for operation of the symmetric algorithm.</value> |
| 22 | + public CipherMode Mode { get => _mode; set => _mode = value; } |
65 | 23 |
|
66 | 24 | /// <summary> |
67 | | - /// Decrypt the array of bytes. |
| 25 | + /// Gets or sets the secret key for the symmetric algorithm. |
68 | 26 | /// </summary> |
69 | | - /// <param name="key">The secret key to use for the symmetric algorithm.</param> |
70 | | - /// <param name="data">The encrypted array of byte for decryption</param> |
71 | | - /// <returns>The decrypted array of bytes</returns> |
72 | | - public byte[] Decrypt(byte[] key, byte[] data) |
73 | | - { |
74 | | - byte[] buf = null; |
75 | | - |
76 | | - if (Mode == CipherMode.ECB) |
77 | | - { |
78 | | - buf = DecryptAesEcb(key, data); |
79 | | - } |
80 | | - |
81 | | - return buf; |
82 | | - } |
| 27 | + /// <value>The secret key for the symmetric algorithm.</value> |
| 28 | + public byte[] Key { get => _key; set => _key = value; } |
83 | 29 |
|
84 | 30 | /// <summary> |
85 | | - /// Encrypt the array of bytes In ECB Mode |
| 31 | + /// Initializes a new instance of the <see cref="Aes"/> class. |
86 | 32 | /// </summary> |
87 | | - /// <param name="key">The secret key to use for the symmetric algorithm.</param> |
88 | | - /// <param name="data">Array of byte for encryption</param> |
89 | | - /// <returns>The encrypted array of bytes</returns> |
90 | | - private byte[] EncryptAesEcb(byte[] key, byte[] data) |
| 33 | + /// <remarks> |
| 34 | + /// This implementation of the AES is specific to .NET nanoFramework. |
| 35 | + /// </remarks> |
| 36 | + public Aes(CipherMode mode) |
91 | 37 | { |
92 | | - int blockSize = 16; // AES block size is 128 bits (16 bytes) |
93 | | - int blockCount = data.Length / blockSize; |
94 | | - int remainder = data.Length % blockSize; |
95 | | - |
96 | | - byte[] encryptedData = new byte[data.Length]; |
97 | | - |
98 | | - for (int i = 0; i < blockCount; i++) |
99 | | - { |
100 | | - byte[] block = new byte[blockSize]; |
101 | | - Array.Copy(data, i * blockSize, block, 0, blockSize); |
102 | | - EncryptBlock(key, block); |
103 | | - Array.Copy(block, 0, encryptedData, i * blockSize, blockSize); |
104 | | - } |
105 | | - |
106 | | - // If there is a remainder, pad the last block and encrypt |
107 | | - if (remainder > 0) |
108 | | - { |
109 | | - byte[] lastBlock = new byte[blockSize]; |
110 | | - Array.Copy(data, blockCount * blockSize, lastBlock, 0, remainder); |
111 | | - EncryptBlock(key, lastBlock); |
112 | | - Array.Copy(lastBlock, 0, encryptedData, blockCount * blockSize, remainder); |
113 | | - } |
114 | | - |
115 | | - return encryptedData; |
| 38 | + Mode = mode; |
116 | 39 | } |
117 | 40 |
|
118 | 41 | /// <summary> |
119 | | - /// XOR the block of data with key |
| 42 | + /// Encrypts data using the cipher specified in <see cref="Mode"/>. |
120 | 43 | /// </summary> |
121 | | - /// <param name="key">The secret key to use for the symmetric algorithm.</param> |
122 | | - /// <param name="block">The block of data for XOR opration with secret key</param> |
123 | | - /// <exception cref="ArgumentException">Key and block must have the same length.</exception> |
124 | | - private void EncryptBlock(byte[] key, byte[] block) |
| 44 | + /// <param name="data">The data to encrypt.</param> |
| 45 | + /// <returns>The encrypted ciphertext data.</returns> |
| 46 | + /// <exception cref="InvalidOperationException">If the <see cref="Key"/> hasn't been set.</exception> |
| 47 | + /// <exception cref="ArgumentException">If the data in not a multiple of the block size (16 bytes for AES).</exception> |
| 48 | + public byte[] Encrypt(byte[] data) |
125 | 49 | { |
126 | | - // Ensure that the key and block have the same length |
127 | | - if (key.Length != block.Length) |
| 50 | + if (Mode == CipherMode.ECB) |
128 | 51 | { |
129 | | - throw new ArgumentException(); |
| 52 | + return EncryptAesEcb(data); |
130 | 53 | } |
131 | 54 |
|
132 | | - for (int i = 0; i < block.Length; i++) |
133 | | - { |
134 | | - block[i] = (byte)(block[i] ^ key[i]); |
135 | | - } |
| 55 | + throw new NotSupportedException(); |
136 | 56 | } |
137 | 57 |
|
138 | 58 | /// <summary> |
139 | | - /// Decrypt the array of bytes In ECB Mode |
| 59 | + /// Decrypts data using cipher specified in <see cref="Mode"/>. |
140 | 60 | /// </summary> |
141 | | - /// <param name="key">The secret key to use for the symmetric algorithm.</param> |
142 | | - /// <param name="data">The encrypted array of byte for decryption</param> |
143 | | - /// <returns>The decrypted array of bytes</returns> |
144 | | - private byte[] DecryptAesEcb(byte[] key, byte[] data) |
| 61 | + /// <param name="data">The data to decrypt.</param> |
| 62 | + /// <returns>The decrypted plaintext data.</returns> |
| 63 | + /// <exception cref="InvalidOperationException">If the <see cref="Key"/> hasn't been set.</exception> |
| 64 | + /// <exception cref="ArgumentException">If the data in not a multiple of the block size (16 bytes for AES).</exception> |
| 65 | + public byte[] Decrypt(byte[] data) |
145 | 66 | { |
146 | | - int blockSize = 16; // AES block size is 128 bits (16 bytes) |
147 | | - int blockCount = data.Length / blockSize; |
148 | | - int remainder = data.Length % blockSize; |
149 | | - |
150 | | - byte[] decryptedData = new byte[data.Length]; |
151 | | - |
152 | | - for (int i = 0; i < blockCount; i++) |
153 | | - { |
154 | | - byte[] block = new byte[blockSize]; |
155 | | - Array.Copy(data, i * blockSize, block, 0, blockSize); |
156 | | - DecryptBlock(key, block); |
157 | | - Array.Copy(block, 0, decryptedData, i * blockSize, blockSize); |
158 | | - } |
159 | | - |
160 | | - // If there is a remainder, pad the last block and decrypt |
161 | | - if (remainder > 0) |
| 67 | + if (Mode == CipherMode.ECB) |
162 | 68 | { |
163 | | - byte[] lastBlock = new byte[blockSize]; |
164 | | - Array.Copy(data, blockCount * blockSize, lastBlock, 0, remainder); |
165 | | - DecryptBlock(key, lastBlock); |
166 | | - Array.Copy(lastBlock, 0, decryptedData, blockCount * blockSize, remainder); |
| 69 | + return DecryptAesEcb(data); |
167 | 70 | } |
168 | 71 |
|
169 | | - return decryptedData; |
| 72 | + throw new NotSupportedException(); |
170 | 73 | } |
171 | 74 |
|
172 | | - /// <summary> |
173 | | - /// XOR the block of data with key |
174 | | - /// </summary> |
175 | | - /// <param name="key">The secret key to use for the symmetric algorithm.</param> |
176 | | - /// <param name="block">The block of data for XOR opration with secret key</param> |
177 | | - /// <exception cref="ArgumentException">Key and block must have the same length.</exception> |
178 | | - private void DecryptBlock(byte[] key, byte[] block) |
179 | | - { |
180 | | - // Ensure that the key and block have the same length |
181 | | - if (key.Length != block.Length) |
182 | | - { |
183 | | - throw new ArgumentException(); |
184 | | - } |
| 75 | + [MethodImpl(MethodImplOptions.InternalCall)] |
| 76 | + private extern byte[] EncryptAesEcb(byte[] data); |
185 | 77 |
|
186 | | - for (int i = 0; i < block.Length; i++) |
187 | | - { |
188 | | - block[i] = (byte)(block[i] ^ key[i]); |
189 | | - } |
190 | | - } |
| 78 | + [MethodImpl(MethodImplOptions.InternalCall)] |
| 79 | + private extern byte[] DecryptAesEcb(byte[] data); |
191 | 80 | } |
192 | 81 | } |
0 commit comments