2 // PaddingModeTest.cs - NUnit Test Cases for PaddingMode
5 // Sebastien Pouliot (sebastien@ximian.com)
7 // (C) 2003 Motus Technologies Inc. (http://www.motus.com)
8 // Copyright (C) 2004, 2008 Novell, Inc (http://www.novell.com)
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 using System
.Security
.Cryptography
;
33 using NUnit
.Framework
;
35 namespace MonoTests
.System
.Security
.Cryptography
{
38 public class PaddingModeTest
{
40 private static byte[] key1
= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }
;
41 private static byte[] key2
= { 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01 }
;
42 private static byte[] key3
= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }
;
44 public void AssertEquals (string msg
, byte[] array1
, byte[] array2
)
46 Assert
.AreEqual (array1
, array2
, msg
);
49 protected byte[] CombineKeys (byte[] key1
, byte[] key2
, byte[] key3
)
51 int k1l
= key1
.Length
;
52 int k2l
= key2
.Length
;
53 int k3l
= key3
.Length
;
54 byte[] key
= new byte [k1l
+ k2l
+ k3l
];
55 Array
.Copy (key1
, 0, key
, 0, k1l
);
56 Array
.Copy (key2
, 0, key
, k1l
, k2l
);
57 Array
.Copy (key3
, 0, key
, k1l
+ k2l
, k3l
);
61 private byte[] Decrypt (SymmetricAlgorithm algo
, PaddingMode padding
, byte[] data
)
63 algo
.IV
= new byte [algo
.BlockSize
>> 3];
64 algo
.Mode
= CipherMode
.CBC
;
65 algo
.Padding
= padding
;
66 ICryptoTransform ct
= algo
.CreateDecryptor ();
67 return ct
.TransformFinalBlock (data
, 0, data
.Length
);
70 private byte[] Encrypt (SymmetricAlgorithm algo
, PaddingMode padding
, byte[] data
)
72 algo
.IV
= new byte [algo
.BlockSize
>> 3];
73 algo
.Mode
= CipherMode
.CBC
;
74 algo
.Padding
= padding
;
75 ICryptoTransform ct
= algo
.CreateEncryptor ();
76 return ct
.TransformFinalBlock (data
, 0, data
.Length
);
79 private byte[] GetData (byte size
)
81 byte[] data
= new byte [size
];
82 for (byte i
=0; i
< size
; i
++) {
88 private TripleDES
GetTripleDES ()
90 TripleDES tdes
= TripleDES
.Create ();
91 tdes
.Key
= CombineKeys (key1
, key2
, key3
);
96 [ExpectedException (typeof (CryptographicException
))]
97 public void TripleDESNone_SmallerThanOneBlockSize ()
99 TripleDES tdes
= GetTripleDES ();
100 byte[] data
= GetData (7);
101 byte[] encdata
= Encrypt (tdes
, PaddingMode
.None
, data
);
105 public void TripleDESNone_ExactlyOneBlockSize ()
107 TripleDES tdes
= GetTripleDES ();
108 byte[] data
= GetData (8);
109 byte[] encdata
= Encrypt (tdes
, PaddingMode
.None
, data
);
110 Assert
.AreEqual ("23-61-AC-E6-C5-17-10-51", BitConverter
.ToString (encdata
), "TripleDESNone_ExactlyOneBlockSize_Encrypt");
111 byte[] decdata
= Decrypt (tdes
, PaddingMode
.None
, encdata
);
112 AssertEquals ("TripleDESNone_ExactlyOneBlockSize_Decrypt", data
, decdata
);
116 [ExpectedException (typeof (CryptographicException
))]
117 public void TripleDESNone_MoreThanOneBlockSize ()
119 TripleDES tdes
= GetTripleDES ();
120 byte[] data
= GetData (12);
121 byte[] encdata
= Encrypt (tdes
, PaddingMode
.None
, data
);
125 public void TripleDESNone_ExactMultipleBlockSize ()
127 TripleDES tdes
= GetTripleDES ();
128 byte[] data
= GetData (48);
129 byte[] encdata
= Encrypt (tdes
, PaddingMode
.None
, data
);
130 // note: encrypted data is truncated to a multiple of block size
131 Assert
.AreEqual ("23-61-AC-E6-C5-17-10-51-BF-AB-79-9C-CD-5E-79-40-16-81-0D-6B-40-E6-B2-E9-86-34-8A-9E-5D-56-DA-D1-0C-8C-76-0A-E1-69-A1-0A-B5-B5-7F-FC-5A-D0-6E-6A", BitConverter
.ToString (encdata
), "TripleDESNone_ExactMultipleBlockSize_Encrypt");
132 byte[] decdata
= Decrypt (tdes
, PaddingMode
.None
, encdata
);
133 AssertEquals ("TripleDESNone_ExactMultipleBlockSize_Decrypt", GetData (48), decdata
);
137 public void TripleDESPKCS7_SmallerThanOneBlockSize ()
139 TripleDES tdes
= GetTripleDES ();
140 byte[] data
= GetData (7);
141 byte[] encdata
= Encrypt (tdes
, PaddingMode
.PKCS7
, data
);
142 Assert
.AreEqual ("C6-59-0E-E3-7F-26-92-B0", BitConverter
.ToString (encdata
), "TripleDESPKCS7_SmallerThanOneBlockSize_Encrypt");
143 byte[] decdata
= Decrypt (tdes
, PaddingMode
.PKCS7
, encdata
);
144 AssertEquals ("TripleDESPKCS7_SmallerThanOneBlockSize_Decrypt", data
, decdata
);
148 public void TripleDESPKCS7_ExactlyOneBlockSize ()
150 TripleDES tdes
= GetTripleDES ();
151 byte[] data
= GetData (8);
152 byte[] encdata
= Encrypt (tdes
, PaddingMode
.PKCS7
, data
);
153 Assert
.AreEqual ("23-61-AC-E6-C5-17-10-51-C0-60-5B-6A-5C-B7-69-62", BitConverter
.ToString (encdata
), "TripleDESPKCS7_ExactlyOneBlockSize_Encrypt");
154 byte[] decdata
= Decrypt (tdes
, PaddingMode
.PKCS7
, encdata
);
155 AssertEquals ("TripleDESPKCS7_ExactlyOneBlockSize_Decrypt", data
, decdata
);
159 public void TripleDESPKCS7_MoreThanOneBlockSize ()
161 TripleDES tdes
= GetTripleDES ();
162 byte[] data
= GetData (12);
163 byte[] encdata
= Encrypt (tdes
, PaddingMode
.PKCS7
, data
);
164 Assert
.AreEqual ("23-61-AC-E6-C5-17-10-51-D9-CB-92-8C-76-89-35-84", BitConverter
.ToString (encdata
), "TripleDESPKCS7_MoreThanOneBlockSize_Encrypt");
165 byte[] decdata
= Decrypt (tdes
, PaddingMode
.PKCS7
, encdata
);
166 AssertEquals ("TripleDESPKCS7_MoreThanOneBlockSize_Decrypt", data
, decdata
);
170 public void TripleDESPKCS7_ExactMultipleBlockSize ()
172 TripleDES tdes
= GetTripleDES ();
173 byte[] data
= GetData (48);
174 byte[] encdata
= Encrypt (tdes
, PaddingMode
.PKCS7
, data
);
175 Assert
.AreEqual ("23-61-AC-E6-C5-17-10-51-BF-AB-79-9C-CD-5E-79-40-16-81-0D-6B-40-E6-B2-E9-86-34-8A-9E-5D-56-DA-D1-0C-8C-76-0A-E1-69-A1-0A-B5-B5-7F-FC-5A-D0-6E-6A-73-61-63-1C-58-A2-9C-B3", BitConverter
.ToString (encdata
), "TripleDESPKCS7_ExactMultipleBlockSize_Encrypt");
176 byte[] decdata
= Decrypt (tdes
, PaddingMode
.PKCS7
, encdata
);
177 AssertEquals ("TripleDESPKCS7_ExactMultipleBlockSize_Decrypt", data
, decdata
);
181 public void TripleDESZeros_SmallerThanOneBlockSize ()
183 TripleDES tdes
= GetTripleDES ();
184 byte[] data
= GetData (7);
185 byte[] encdata
= Encrypt (tdes
, PaddingMode
.Zeros
, data
);
186 Assert
.AreEqual ("B8-5C-5B-A5-06-0B-7E-C6", BitConverter
.ToString (encdata
), "TripleDESZeros_SmallerThanOneBlockSize_Encrypt");
187 byte[] decdata
= Decrypt (tdes
, PaddingMode
.Zeros
, encdata
);
188 Assert
.AreEqual ("00-01-02-03-04-05-06-00", BitConverter
.ToString (decdata
), "TripleDESZeros_SmallerThanOneBlockSize_Decrypt");
192 public void TripleDESZeros_ExactlyOneBlockSize ()
194 TripleDES tdes
= GetTripleDES ();
195 byte[] data
= GetData (8);
196 byte[] encdata
= Encrypt (tdes
, PaddingMode
.Zeros
, data
);
197 Assert
.AreEqual ("23-61-AC-E6-C5-17-10-51", BitConverter
.ToString (encdata
), "TripleDESZeros_ExactlyOneBlockSize_Encrypt");
198 byte[] decdata
= Decrypt (tdes
, PaddingMode
.Zeros
, encdata
);
199 AssertEquals ("TripleDESZeros_ExactlyOneBlockSize_Decrypt", data
, decdata
);
203 public void TripleDESZeros_MoreThanOneBlockSize ()
205 TripleDES tdes
= GetTripleDES ();
206 byte[] data
= GetData (12);
207 byte[] encdata
= Encrypt (tdes
, PaddingMode
.Zeros
, data
);
208 Assert
.AreEqual ("23-61-AC-E6-C5-17-10-51-6E-75-2E-33-12-09-5D-66", BitConverter
.ToString (encdata
), "TripleDESZeros_MoreThanOneBlockSize_Encrypt");
209 byte[] decdata
= Decrypt (tdes
, PaddingMode
.Zeros
, encdata
);
210 Assert
.AreEqual ("00-01-02-03-04-05-06-07-08-09-0A-0B-00-00-00-00", BitConverter
.ToString (decdata
), "TripleDESZeros_MoreThanOneBlockSize_Decrypt");
214 public void TripleDESZeros_ExactMultipleBlockSize ()
216 TripleDES tdes
= GetTripleDES ();
217 byte[] data
= GetData (48);
218 byte[] encdata
= Encrypt (tdes
, PaddingMode
.Zeros
, data
);
219 Assert
.AreEqual ("23-61-AC-E6-C5-17-10-51-BF-AB-79-9C-CD-5E-79-40-16-81-0D-6B-40-E6-B2-E9-86-34-8A-9E-5D-56-DA-D1-0C-8C-76-0A-E1-69-A1-0A-B5-B5-7F-FC-5A-D0-6E-6A", BitConverter
.ToString (encdata
), "TripleDESZeros_ExactMultipleBlockSize_Encrypt");
220 byte[] decdata
= Decrypt (tdes
, PaddingMode
.Zeros
, encdata
);
221 AssertEquals ("TripleDESZeros_ExactMultipleBlockSize_Decrypt", GetData (48), decdata
);
224 private Rijndael
GetAES ()
226 Rijndael aes
= Rijndael
.Create ();
227 aes
.Key
= CombineKeys (key1
, key2
, key3
);
232 [ExpectedException (typeof (CryptographicException
))]
233 public void RijndaelNone_SmallerThanOneBlockSize ()
235 Rijndael aes
= GetAES ();
236 byte[] data
= GetData (8);
237 byte[] encdata
= Encrypt (aes
, PaddingMode
.None
, data
);
241 public void RijndaelNone_ExactlyOneBlockSize ()
243 Rijndael aes
= GetAES ();
244 byte[] data
= GetData (16);
245 byte[] encdata
= Encrypt (aes
, PaddingMode
.None
, data
);
246 Assert
.AreEqual ("79-42-36-2F-D6-DB-F1-0C-87-99-58-06-D5-F6-B0-BB", BitConverter
.ToString (encdata
), "RijndaelNone_ExactlyOneBlockSize_Encrypt");
247 byte[] decdata
= Decrypt (aes
, PaddingMode
.None
, encdata
);
248 AssertEquals ("RijndaelNone_ExactlyOneBlockSize_Decrypt", data
, decdata
);
252 [ExpectedException (typeof (CryptographicException
))]
253 public void RijndaelNone_MoreThanOneBlockSize ()
255 Rijndael aes
= GetAES ();
256 byte[] data
= GetData (20);
257 byte[] encdata
= Encrypt (aes
, PaddingMode
.None
, data
);
261 public void RijndaelNone_ExactMultipleBlockSize ()
263 Rijndael aes
= GetAES ();
264 byte[] data
= GetData (48);
265 byte[] encdata
= Encrypt (aes
, PaddingMode
.None
, data
);
266 // note: encrypted data is truncated to a multiple of block size
267 Assert
.AreEqual ("79-42-36-2F-D6-DB-F1-0C-87-99-58-06-D5-F6-B0-BB-E1-27-3E-21-5A-BE-D5-12-F4-AF-06-8D-0A-BD-02-64-02-CB-FF-D7-32-19-5E-69-3C-54-C2-8C-A1-D7-72-FF", BitConverter
.ToString (encdata
), "RijndaelNone_ExactMultipleBlockSize_Encrypt");
268 byte[] decdata
= Decrypt (aes
, PaddingMode
.None
, encdata
);
269 AssertEquals ("RijndaelNone_ExactMultipleBlockSize_Decrypt", GetData (48), decdata
);
273 public void RijndaelPKCS7_SmallerThanOneBlockSize ()
275 Rijndael aes
= GetAES ();
276 byte[] data
= GetData (8);
277 byte[] encdata
= Encrypt (aes
, PaddingMode
.PKCS7
, data
);
278 Assert
.AreEqual ("AB-E0-20-5E-BC-28-A0-B7-A7-56-A3-BF-13-55-13-7E", BitConverter
.ToString (encdata
), "RijndaelPKCS7_SmallerThanOneBlockSize_Encrypt");
279 byte[] decdata
= Decrypt (aes
, PaddingMode
.PKCS7
, encdata
);
280 AssertEquals ("RijndaelPKCS7_SmallerThanOneBlockSize_Decrypt", data
, decdata
);
284 public void RijndaelPKCS7_ExactlyOneBlockSize ()
286 Rijndael aes
= GetAES ();
287 byte[] data
= GetData (16);
288 byte[] encdata
= Encrypt (aes
, PaddingMode
.PKCS7
, data
);
289 Assert
.AreEqual ("79-42-36-2F-D6-DB-F1-0C-87-99-58-06-D5-F6-B0-BB-60-CE-9F-E0-72-3B-D6-D1-A5-F8-33-D8-25-31-7F-D4", BitConverter
.ToString (encdata
), "RijndaelPKCS7_ExactlyOneBlockSize_Encrypt");
290 byte[] decdata
= Decrypt (aes
, PaddingMode
.PKCS7
, encdata
);
291 AssertEquals ("RijndaelPKCS7_ExactlyOneBlockSize_Decrypt", data
, decdata
);
295 public void RijndaelPKCS7_MoreThanOneBlockSize ()
297 Rijndael aes
= GetAES ();
298 byte[] data
= GetData (20);
299 byte[] encdata
= Encrypt (aes
, PaddingMode
.PKCS7
, data
);
300 Assert
.AreEqual ("79-42-36-2F-D6-DB-F1-0C-87-99-58-06-D5-F6-B0-BB-06-3F-D3-51-8D-55-E9-2F-02-4A-4E-F2-91-55-31-83", BitConverter
.ToString (encdata
), "RijndaelPKCS7_MoreThanOneBlockSize_Encrypt");
301 byte[] decdata
= Decrypt (aes
, PaddingMode
.PKCS7
, encdata
);
302 AssertEquals ("RijndaelPKCS7_MoreThanOneBlockSize_Decrypt", data
, decdata
);
306 public void RijndaelPKCS7_ExactMultipleBlockSize ()
308 Rijndael aes
= GetAES ();
309 byte[] data
= GetData (48);
310 byte[] encdata
= Encrypt (aes
, PaddingMode
.PKCS7
, data
);
311 Assert
.AreEqual ("79-42-36-2F-D6-DB-F1-0C-87-99-58-06-D5-F6-B0-BB-E1-27-3E-21-5A-BE-D5-12-F4-AF-06-8D-0A-BD-02-64-02-CB-FF-D7-32-19-5E-69-3C-54-C2-8C-A1-D7-72-FF-37-42-81-21-47-A7-E0-AA-64-A7-8B-65-25-95-AA-54", BitConverter
.ToString (encdata
), "RijndaelPKCS7_ExactMultipleBlockSize_Encrypt");
312 byte[] decdata
= Decrypt (aes
, PaddingMode
.PKCS7
, encdata
);
313 AssertEquals ("RijndaelPKCS7_ExactMultipleBlockSize_Decrypt", data
, decdata
);
317 public void RijndaelZeros_SmallerThanOneBlockSize ()
319 Rijndael aes
= GetAES ();
320 byte[] data
= GetData (8);
321 byte[] encdata
= Encrypt (aes
, PaddingMode
.Zeros
, data
);
322 Assert
.AreEqual ("DD-BE-D7-CE-E2-DD-5C-A3-3E-44-A1-76-00-E5-5B-5D", BitConverter
.ToString (encdata
), "RijndaelZeros_SmallerThanOneBlockSize_Encrypt");
323 byte[] decdata
= Decrypt (aes
, PaddingMode
.Zeros
, encdata
);
324 Assert
.AreEqual ("00-01-02-03-04-05-06-07-00-00-00-00-00-00-00-00", BitConverter
.ToString (decdata
), "RijndaelZeros_SmallerThanOneBlockSize_Decrypt");
328 public void RijndaelZeros_ExactlyOneBlockSize ()
330 Rijndael aes
= GetAES ();
331 byte[] data
= GetData (16);
332 byte[] encdata
= Encrypt (aes
, PaddingMode
.Zeros
, data
);
333 Assert
.AreEqual ("79-42-36-2F-D6-DB-F1-0C-87-99-58-06-D5-F6-B0-BB", BitConverter
.ToString (encdata
), "RijndaelZeros_ExactlyOneBlockSize_Encrypt");
334 byte[] decdata
= Decrypt (aes
, PaddingMode
.Zeros
, encdata
);
335 AssertEquals ("RijndaelZeros_ExactlyOneBlockSize_Decrypt", data
, decdata
);
339 public void RijndaelZeros_MoreThanOneBlockSize ()
341 Rijndael aes
= GetAES ();
342 byte[] data
= GetData (20);
343 byte[] encdata
= Encrypt (aes
, PaddingMode
.Zeros
, data
);
344 Assert
.AreEqual ("79-42-36-2F-D6-DB-F1-0C-87-99-58-06-D5-F6-B0-BB-04-6C-F7-A5-DE-FF-B4-30-29-7A-0E-04-3B-D4-B8-F2", BitConverter
.ToString (encdata
), "RijndaelZeros_MoreThanOneBlockSize_Encrypt");
345 byte[] decdata
= Decrypt (aes
, PaddingMode
.Zeros
, encdata
);
346 Assert
.AreEqual ("00-01-02-03-04-05-06-07-08-09-0A-0B-0C-0D-0E-0F-10-11-12-13-00-00-00-00-00-00-00-00-00-00-00-00", BitConverter
.ToString (decdata
), "RijndaelZeros_MoreThanOneBlockSize_Decrypt");
350 public void RijndaelZeros_ExactMultipleBlockSize ()
352 Rijndael aes
= GetAES ();
353 byte[] data
= GetData (48);
354 byte[] encdata
= Encrypt (aes
, PaddingMode
.Zeros
, data
);
355 Assert
.AreEqual ("79-42-36-2F-D6-DB-F1-0C-87-99-58-06-D5-F6-B0-BB-E1-27-3E-21-5A-BE-D5-12-F4-AF-06-8D-0A-BD-02-64-02-CB-FF-D7-32-19-5E-69-3C-54-C2-8C-A1-D7-72-FF", BitConverter
.ToString (encdata
), "RijndaelZeros_ExactMultipleBlockSize_Encrypt");
356 byte[] decdata
= Decrypt (aes
, PaddingMode
.Zeros
, encdata
);
357 AssertEquals ("RijndaelZeros_ExactMultipleBlockSize_Decrypt", GetData (48), decdata
);
363 public void PaddingModeEnum ()
365 Assert
.AreEqual (4, (int)PaddingMode
.ANSIX923
, "ANSIX923");
366 Assert
.AreEqual (5, (int)PaddingMode
.ISO10126
, "ISO10126");
367 Assert
.AreEqual (1, (int)PaddingMode
.None
, "None");
368 Assert
.AreEqual (2, (int)PaddingMode
.PKCS7
, "PKCS7");
369 Assert
.AreEqual (3, (int)PaddingMode
.Zeros
, "Zeros");
372 // SymmetricAlgorithm tests
374 private byte[] GetKey (SymmetricAlgorithm sa
)
376 byte[] key
= new byte [sa
.KeySize
>> 3];
377 // no weak key this way (DES, TripleDES)
378 for (byte i
=0; i
< key
.Length
; i
++)
383 private byte[] GetIV (SymmetricAlgorithm sa
)
385 return new byte [sa
.BlockSize
>> 3];
388 private ICryptoTransform
GetEncryptor (SymmetricAlgorithm sa
, PaddingMode mode
)
390 sa
.Mode
= CipherMode
.ECB
; // basic (no) mode
392 return sa
.CreateEncryptor (GetKey (sa
), GetIV (sa
));
395 private ICryptoTransform
GetDecryptor (SymmetricAlgorithm sa
, PaddingMode mode
)
397 sa
.Mode
= CipherMode
.ECB
; // basic (no) mode
399 return sa
.CreateDecryptor (GetKey (sa
), GetIV (sa
));
402 // the best way to verify padding is to:
403 // a. encrypt data larger than one block with a padding mode "X"
404 // b. decrypt the data with padding mode "None"
405 // c. compare the last (padding) bytes with the expected padding
406 private void ANSIX923_Full (SymmetricAlgorithm sa
)
408 int bs
= (sa
.BlockSize
>> 3);
410 byte[] data
= new byte [bs
]; // in bytes
411 ICryptoTransform enc
= GetEncryptor (sa
, PaddingMode
.ANSIX923
);
412 byte[] encdata
= enc
.TransformFinalBlock (data
, 0, data
.Length
);
413 // one block of padding is added
414 Assert
.AreEqual (data
.Length
* 2, encdata
.Length
, "one more block added");
416 ICryptoTransform dec
= GetDecryptor (sa
, PaddingMode
.None
);
417 byte[] decdata
= dec
.TransformFinalBlock (encdata
, 0, encdata
.Length
);
418 Assert
.AreEqual (encdata
.Length
, decdata
.Length
, "no unpadding");
420 int pd
= decdata
.Length
- data
.Length
;
421 // now validate padding - ANSI X.923 is all 0 except last byte (length)
422 for (int i
=0; i
< bs
- 1; i
++)
423 Assert
.AreEqual (0x00, decdata
[decdata
.Length
- pd
+ i
], i
.ToString ());
424 Assert
.AreEqual (pd
, decdata
[decdata
.Length
- 1], "last byte");
427 private void ANSIX923_Partial (SymmetricAlgorithm sa
)
429 int bs
= (sa
.BlockSize
>> 3);
430 // one and an half block
431 byte[] data
= new byte [bs
+ (bs
>> 1)]; // in bytes
432 ICryptoTransform enc
= GetEncryptor (sa
, PaddingMode
.ANSIX923
);
433 byte[] encdata
= enc
.TransformFinalBlock (data
, 0, data
.Length
);
434 // one block of padding is added
435 Assert
.AreEqual (bs
* 2, encdata
.Length
, "one more block added");
437 ICryptoTransform dec
= GetDecryptor (sa
, PaddingMode
.None
);
438 byte[] decdata
= dec
.TransformFinalBlock (encdata
, 0, encdata
.Length
);
439 Assert
.AreEqual (encdata
.Length
, decdata
.Length
, "no unpadding");
441 int pd
= decdata
.Length
- data
.Length
;
442 // now validate padding - ANSI X.923 is all 0 except last byte (length)
443 for (int i
= 0; i
< pd
- 1; i
++)
444 Assert
.AreEqual (0x00, decdata
[decdata
.Length
- pd
+ i
], i
.ToString ());
445 Assert
.AreEqual (pd
, decdata
[decdata
.Length
- 1], "last byte");
448 private void ISO10126_Full (SymmetricAlgorithm sa
)
450 int bs
= (sa
.BlockSize
>> 3);
452 byte [] data
= new byte [bs
]; // in bytes
453 ICryptoTransform enc
= GetEncryptor (sa
, PaddingMode
.ISO10126
);
454 byte [] encdata
= enc
.TransformFinalBlock (data
, 0, data
.Length
);
455 // one block of padding is added
456 Assert
.AreEqual (data
.Length
* 2, encdata
.Length
, "one more block added");
458 ICryptoTransform dec
= GetDecryptor (sa
, PaddingMode
.None
);
459 byte [] decdata
= dec
.TransformFinalBlock (encdata
, 0, encdata
.Length
);
460 Assert
.AreEqual (encdata
.Length
, decdata
.Length
, "no unpadding");
462 int pd
= decdata
.Length
- data
.Length
;
463 // now validate padding - ISO10126 is all random except last byte (length)
464 Assert
.AreEqual (pd
, decdata
[decdata
.Length
- 1], "last byte");
467 private void ISO10126_Partial (SymmetricAlgorithm sa
)
469 int bs
= (sa
.BlockSize
>> 3);
470 // one and an half block
471 byte [] data
= new byte [bs
+ (bs
>> 1)]; // in bytes
472 ICryptoTransform enc
= GetEncryptor (sa
, PaddingMode
.ISO10126
);
473 byte [] encdata
= enc
.TransformFinalBlock (data
, 0, data
.Length
);
474 // one block of padding is added
475 Assert
.AreEqual (bs
* 2, encdata
.Length
, "one more block added");
477 ICryptoTransform dec
= GetDecryptor (sa
, PaddingMode
.None
);
478 byte [] decdata
= dec
.TransformFinalBlock (encdata
, 0, encdata
.Length
);
479 Assert
.AreEqual (encdata
.Length
, decdata
.Length
, "no unpadding");
481 int pd
= decdata
.Length
- data
.Length
;
482 // now validate padding - ISO10126 is all random except last byte (length)
483 Assert
.AreEqual (pd
, decdata
[decdata
.Length
- 1], "last byte");
485 private void PKCS7_Full (SymmetricAlgorithm sa
)
487 int bs
= (sa
.BlockSize
>> 3);
489 byte[] data
= new byte [bs
]; // in bytes
490 ICryptoTransform enc
= GetEncryptor (sa
, PaddingMode
.PKCS7
);
491 byte[] encdata
= enc
.TransformFinalBlock (data
, 0, data
.Length
);
492 // one block of padding is added
493 Assert
.AreEqual (data
.Length
* 2, encdata
.Length
, "one more block added");
495 ICryptoTransform dec
= GetDecryptor (sa
, PaddingMode
.None
);
496 byte[] decdata
= dec
.TransformFinalBlock (encdata
, 0, encdata
.Length
);
497 Assert
.AreEqual (encdata
.Length
, decdata
.Length
, "no unpadding");
499 int pd
= decdata
.Length
- data
.Length
;
500 // now validate padding - PKCS7 is all padding char
501 for (int i
= 0; i
< bs
; i
++)
502 Assert
.AreEqual (pd
, decdata
[decdata
.Length
- pd
+ i
], i
.ToString ());
505 private void PKCS7_Partial (SymmetricAlgorithm sa
)
507 int bs
= (sa
.BlockSize
>> 3);
508 // one and an half block
509 byte[] data
= new byte[bs
+ (bs
>> 1)]; // in bytes
510 ICryptoTransform enc
= GetEncryptor (sa
, PaddingMode
.PKCS7
);
511 byte[] encdata
= enc
.TransformFinalBlock (data
, 0, data
.Length
);
512 // one block of padding is added
513 Assert
.AreEqual (bs
* 2, encdata
.Length
, "one more block added");
515 ICryptoTransform dec
= GetDecryptor (sa
, PaddingMode
.None
);
516 byte[] decdata
= dec
.TransformFinalBlock (encdata
, 0, encdata
.Length
);
517 Assert
.AreEqual (encdata
.Length
, decdata
.Length
, "no unpadding");
519 int pd
= decdata
.Length
- data
.Length
;
520 // now validate padding - PKCS7 is all padding char
521 for (int i
= 0; i
< pd
; i
++)
522 Assert
.AreEqual (pd
, decdata
[decdata
.Length
- pd
+ i
], i
.ToString ());
525 private void Zeros_Full (SymmetricAlgorithm sa
)
527 int bs
= (sa
.BlockSize
>> 3);
529 byte [] data
= new byte [bs
]; // in bytes
530 for (int i
= 0; i
< data
.Length
; i
++)
533 ICryptoTransform enc
= GetEncryptor (sa
, PaddingMode
.Zeros
);
534 byte [] encdata
= enc
.TransformFinalBlock (data
, 0, data
.Length
);
535 // NO extra block is used for zero padding
536 Assert
.AreEqual (data
.Length
, encdata
.Length
, "no extra block added");
538 ICryptoTransform dec
= GetDecryptor (sa
, PaddingMode
.None
);
539 byte [] decdata
= dec
.TransformFinalBlock (encdata
, 0, encdata
.Length
);
540 Assert
.AreEqual (encdata
.Length
, decdata
.Length
, "no unpadding");
542 // now validate absence of padding
543 Assert
.AreEqual (0xFF, decdata
[decdata
.Length
- 1], "no padding");
546 private void Zeros_Partial (SymmetricAlgorithm sa
)
548 int bs
= (sa
.BlockSize
>> 3);
549 // one and an half block
550 byte [] data
= new byte [bs
+ (bs
>> 1)]; // in bytes
551 for (int i
=0; i
< data
.Length
; i
++)
554 ICryptoTransform enc
= GetEncryptor (sa
, PaddingMode
.Zeros
);
555 byte [] encdata
= enc
.TransformFinalBlock (data
, 0, data
.Length
);
556 // one block of padding is added
557 Assert
.AreEqual (bs
* 2, encdata
.Length
, "one more block added");
559 ICryptoTransform dec
= GetDecryptor (sa
, PaddingMode
.None
);
560 byte [] decdata
= dec
.TransformFinalBlock (encdata
, 0, encdata
.Length
);
561 Assert
.AreEqual (encdata
.Length
, decdata
.Length
, "no unpadding");
563 int pd
= decdata
.Length
- data
.Length
;
564 // now validate padding - Zeros is all 0x00 char
565 for (int i
= 0; i
< pd
; i
++)
566 Assert
.AreEqual (0x00, decdata
[decdata
.Length
- pd
+ i
], i
.ToString ());
571 public void DES_ANSIX923_Full ()
573 ANSIX923_Full (DES
.Create ());
577 public void DES_ANSIX923_Partial ()
579 ANSIX923_Partial (DES
.Create ());
583 public void RC2_ANSIX923_Full ()
585 ANSIX923_Full (RC2
.Create ());
589 public void RC2_ANSIX923_Partial ()
591 ANSIX923_Partial (RC2
.Create ());
595 public void Rijndael_ANSIX923_Full ()
597 ANSIX923_Full (Rijndael
.Create ());
601 public void Rijndael_ANSIX923_Partial ()
603 ANSIX923_Partial (Rijndael
.Create ());
607 public void TripleDES_ANSIX923_Full ()
609 ANSIX923_Full (TripleDES
.Create ());
613 public void TripleDES_ANSIX923_Partial ()
615 ANSIX923_Partial (TripleDES
.Create ());
621 public void DES_ISO10126_Full ()
623 ISO10126_Full (DES
.Create ());
627 public void DES_ISO10126_Partial ()
629 ISO10126_Partial (DES
.Create ());
633 public void RC2_ISO10126_Full ()
635 ISO10126_Full (RC2
.Create ());
639 public void RC2_ISO10126_Partial ()
641 ISO10126_Partial (RC2
.Create ());
645 public void Rijndael_ISO10126_Full ()
647 ISO10126_Full (Rijndael
.Create ());
651 public void Rijndael_ISO10126_Partial ()
653 ISO10126_Partial (Rijndael
.Create ());
657 public void TripleDES_ISO10126_Full ()
659 ISO10126_Full (TripleDES
.Create ());
663 public void TripleDES_ISO10126_Partial ()
665 ISO10126_Partial (TripleDES
.Create ());
670 public void DES_PKCS7_Full ()
672 PKCS7_Full (DES
.Create ());
676 public void DES_PKCS7_Partial ()
678 PKCS7_Partial (DES
.Create ());
682 public void RC2_PKCS7_Full ()
684 PKCS7_Full (RC2
.Create ());
688 public void RC2_PKCS7_Partial ()
690 PKCS7_Partial (RC2
.Create ());
694 public void Rijndael_PKCS7_Full ()
696 PKCS7_Full (Rijndael
.Create ());
700 public void Rijndael_PKCS7_Partial ()
702 PKCS7_Partial (Rijndael
.Create ());
706 public void TripleDES_PKCS7_Full ()
708 PKCS7_Full (TripleDES
.Create ());
712 public void TripleDES_PKCS7_Partial ()
714 PKCS7_Partial (TripleDES
.Create ());
720 public void DES_Zeros_Full ()
722 Zeros_Full (DES
.Create ());
726 public void DES_Zeros_Partial ()
728 Zeros_Partial (DES
.Create ());
732 public void RC2_Zeros_Full ()
734 Zeros_Full (RC2
.Create ());
738 public void RC2_Zeros_Partial ()
740 Zeros_Partial (RC2
.Create ());
744 public void Rijndael_Zeros_Full ()
746 Zeros_Full (Rijndael
.Create ());
750 public void Rijndael_Zeros_Partial ()
752 Zeros_Partial (Rijndael
.Create ());
756 public void TripleDES_Zeros_Full ()
758 Zeros_Full (TripleDES
.Create ());
762 public void TripleDES_Zeros_Partial ()
764 Zeros_Partial (TripleDES
.Create ());
767 // Padding mismatches
769 // the best way to test bad padding is to:
770 // a. encrypt data larger than one block with a padding mode "X"
771 // b. decrypt the data with padding mode "Y" (different with Y)
772 // c. check if the "bad" padding was removed correctly
775 // 1 - length difference
776 // 2 - original data lost
777 // 4 - CryptographicException thrown while decryption
778 private int Mismatch (PaddingMode encrypt
, PaddingMode decrypt
)
780 SymmetricAlgorithm sa
= SymmetricAlgorithm
.Create ();
781 int bs
= (sa
.BlockSize
>> 3);
783 byte [] data
= new byte [bs
]; // in bytes
784 ICryptoTransform enc
= GetEncryptor (sa
, encrypt
);
785 byte [] encdata
= enc
.TransformFinalBlock (data
, 0, data
.Length
);
789 ICryptoTransform dec
= GetDecryptor (sa
, decrypt
);
790 byte [] decdata
= dec
.TransformFinalBlock (encdata
, 0, encdata
.Length
);
792 if (data
.Length
!= decdata
.Length
)
795 for (int i
=0; i
< data
.Length
; i
++) {
796 if (data
[i
] != decdata
[i
]) {
802 catch (CryptographicException
) {
808 public void ANSIX923_ISO10126 ()
810 Assert
.AreEqual (0, Mismatch (PaddingMode
.ANSIX923
, PaddingMode
.ISO10126
));
814 public void ANSIX923_None ()
816 Assert
.AreEqual (1, Mismatch (PaddingMode
.ANSIX923
, PaddingMode
.None
));
820 public void ANSIX923_PKCS7 ()
822 Assert
.AreEqual (4, Mismatch (PaddingMode
.ANSIX923
, PaddingMode
.PKCS7
));
826 public void ANSIX923_Zeros ()
828 Assert
.AreEqual (1, Mismatch (PaddingMode
.ANSIX923
, PaddingMode
.Zeros
));
832 public void ISO10126_ANSIX923 ()
834 Assert
.AreEqual (4, Mismatch (PaddingMode
.ISO10126
, PaddingMode
.ANSIX923
));
838 public void ISO10126_None ()
840 Assert
.AreEqual (1, Mismatch (PaddingMode
.ISO10126
, PaddingMode
.None
));
844 public void ISO10126_PKCS7 ()
846 Assert
.AreEqual (4, Mismatch (PaddingMode
.ISO10126
, PaddingMode
.PKCS7
));
850 public void ISO10126_Zeros ()
852 Assert
.AreEqual (1, Mismatch (PaddingMode
.ISO10126
, PaddingMode
.Zeros
));
856 public void None_ANSIX923 ()
858 Assert
.AreEqual (4, Mismatch (PaddingMode
.None
, PaddingMode
.ANSIX923
));
862 public void None_ISO10126 ()
864 Assert
.AreEqual (4, Mismatch (PaddingMode
.None
, PaddingMode
.ISO10126
));
867 public void None_PKCS7 ()
869 Assert
.AreEqual (4, Mismatch (PaddingMode
.None
, PaddingMode
.PKCS7
));
873 public void None_Zeros ()
875 Assert
.AreEqual (0, Mismatch (PaddingMode
.None
, PaddingMode
.Zeros
));
878 public void PKCS7_ANSIX923 ()
880 Assert
.AreEqual (4, Mismatch (PaddingMode
.PKCS7
, PaddingMode
.ANSIX923
));
884 public void PKCS7_ISO10126 ()
886 Assert
.AreEqual (0, Mismatch (PaddingMode
.PKCS7
, PaddingMode
.ISO10126
));
889 public void PKCS7_None ()
891 Assert
.AreEqual (1, Mismatch (PaddingMode
.PKCS7
, PaddingMode
.None
));
895 public void PKCS7_Zeros ()
897 Assert
.AreEqual (1, Mismatch (PaddingMode
.PKCS7
, PaddingMode
.Zeros
));
900 public void Zeros_ANSIX923 ()
902 Assert
.AreEqual (4, Mismatch (PaddingMode
.Zeros
, PaddingMode
.ANSIX923
));
906 public void Zeros_ISO10126 ()
908 Assert
.AreEqual (4, Mismatch (PaddingMode
.Zeros
, PaddingMode
.ISO10126
));
911 public void Zeros_None ()
913 Assert
.AreEqual (0, Mismatch (PaddingMode
.Zeros
, PaddingMode
.None
));
917 public void Zeros_PKCS7 ()
919 Assert
.AreEqual (4, Mismatch (PaddingMode
.Zeros
, PaddingMode
.PKCS7
));
922 // MACTripleDES tests
923 private string MAC (PaddingMode padding
, int length
)
925 byte[] key
= new byte [24] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }
;
926 MACTripleDES mac
= new MACTripleDES (key
);
927 mac
.Padding
= padding
;
928 byte[] data
= new byte [length
];
929 byte[] hash
= mac
.TransformFinalBlock (data
, 0, data
.Length
);
930 string result
= BitConverter
.ToString (mac
.Hash
);
934 // Note: TripleDES block size is 8 bytes
937 public void MACTripleDES_ANSIX923 ()
939 Assert
.AreEqual ("F6-61-3E-C8-E4-A4-D1-A8", MAC (PaddingMode
.ANSIX923
, 8), "Full");
940 Assert
.AreEqual ("62-C3-78-B0-27-FC-EB-E0", MAC (PaddingMode
.ANSIX923
, 4), "Partial");
944 public void MACTripleDES_ISO10126 ()
946 // ISO 10126 use random in it's padding so we can't use it to get "repeatable" results
947 // (i.e. each call will get different result). This isn't a padding to use for MACing!!!
948 Assert
.AreEqual (23, MAC (PaddingMode
.ISO10126
, 8).Length
, "Full");
949 Assert
.AreEqual (23, MAC (PaddingMode
.ISO10126
, 4).Length
, "Partial");
953 public void MACTripleDES_None ()
955 Assert
.AreEqual ("46-34-5C-8E-EB-DC-74-5C", MAC (PaddingMode
.None
, 8), "Full");
959 [ExpectedException (typeof (CryptographicException
))]
960 public void MACTripleDES_None_Partial ()
962 // Illegal - must be a multiple of block size
963 MAC (PaddingMode
.None
, 4);
967 public void MACTripleDES_PKCS7 ()
969 Assert
.AreEqual ("17-71-9F-D5-0B-EF-1D-07", MAC (PaddingMode
.PKCS7
, 8), "Full");
970 Assert
.AreEqual ("5B-3A-13-6F-3F-6F-13-22", MAC (PaddingMode
.PKCS7
, 4), "Partial");
974 public void MACTripleDES_Zeros ()
976 Assert
.AreEqual ("46-34-5C-8E-EB-DC-74-5C", MAC (PaddingMode
.Zeros
, 8));
977 Assert
.AreEqual ("46-34-5C-8E-EB-DC-74-5C", MAC (PaddingMode
.Zeros
, 4));
980 // https://bugzilla.novell.com/show_bug.cgi?id=366623
983 public void ANSIX923_366623 ()
985 TripleDES algo
= GetTripleDES ();
986 algo
.IV
= new byte [algo
.BlockSize
>> 3];
987 algo
.Mode
= CipherMode
.ECB
;
988 algo
.Padding
= PaddingMode
.ANSIX923
;
990 ICryptoTransform enc
= algo
.CreateEncryptor ();
991 byte[] data
= new byte [2] { 0xff, 0xff }
;
992 byte[] encdata
= enc
.TransformFinalBlock (data
, 0, 2);
993 ICryptoTransform dec
= algo
.CreateDecryptor ();
994 byte[] decdata
= dec
.TransformFinalBlock (encdata
, 0, encdata
.Length
);
995 Assert
.AreEqual (data
, decdata
);