2005-04-27 Sebastien Pouliot <sebastien@ximian.com>
[mono.git] / mcs / class / corlib / Test / System.Security.Cryptography / Rfc2898DeriveBytesTest.cs
1 //
2 // Rfc2898DeriveBytesTest.cs - NUnit Test Cases for Rfc2898DeriveBytes
3 //
4 // Author:
5 //      Sebastien Pouliot  <spouliot@ximian.com>
6 //
7 // (C) 2003 Motus Technologies Inc. (http://www.motus.com)
8 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
9 //
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:
17 // 
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 // 
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.
28 //
29
30 #if NET_2_0
31
32 using NUnit.Framework;
33
34 using System;
35 using System.Security.Cryptography;
36
37 namespace MonoTests.System.Security.Cryptography {
38
39         // References:
40         // a.   PKCS#5: Password-Based Cryptography Standard 
41         //      http://www.rsasecurity.com/rsalabs/pkcs/pkcs-5/index.html
42         // b.   RFC 3211 - Password-based Encryption for CMS
43         //      http://www.faqs.org/rfcs/rfc3211.html
44
45         [TestFixture]
46         public class Rfc2898DeriveBytesTest : Assertion {
47
48                 public void AssertEquals (string msg, byte[] array1, byte[] array2) 
49                 {
50                         AllTests.AssertEquals (msg, array1, array2);
51                 }
52
53                 static private byte[] salt = { 0x12, 0x34, 0x56, 0x78, 0x78, 0x56, 0x34, 0x12 };
54
55                 [Test]
56                 public void ConstructorPasswordSalt () 
57                 {
58                         Rfc2898DeriveBytes pkcs5 = new Rfc2898DeriveBytes ("password", salt);
59                         AssertEquals ("IterationCount", 1000, pkcs5.IterationCount);
60                         AssertEquals ("Salt", salt, pkcs5.Salt);
61                 }
62
63                 [Test]
64                 [ExpectedException (typeof (ArgumentNullException))]
65                 public void ConstructorPasswordNullSalt () 
66                 {
67                         Rfc2898DeriveBytes pkcs5 = new Rfc2898DeriveBytes (null, salt);
68                 }
69
70                 [Test]
71                 [ExpectedException (typeof (ArgumentNullException))]
72                 public void ConstructorPasswordSaltNull () 
73                 {
74                         Rfc2898DeriveBytes pkcs5 = new Rfc2898DeriveBytes ("password", null);
75                 }
76
77                 [Test]
78                 public void ConstructorPasswordSaltIterations () 
79                 {
80                         Rfc2898DeriveBytes pkcs5 = new Rfc2898DeriveBytes ("password", salt, 5);
81                         AssertEquals ("IterationCount", 5, pkcs5.IterationCount);
82                         AssertEquals ("Salt", salt, pkcs5.Salt);
83                 }
84
85                 [Test]
86                 [ExpectedException (typeof (ArgumentNullException))]
87                 public void ConstructorPasswordNullSaltIterations () 
88                 {
89                         string password = null;
90                         Rfc2898DeriveBytes pkcs5 = new Rfc2898DeriveBytes (password, salt, 5);
91                 }
92
93                 [Test]
94                 [ExpectedException (typeof (ArgumentNullException))]
95                 public void ConstructorPasswordSaltNullIterations () 
96                 {
97                         Rfc2898DeriveBytes pkcs5 = new Rfc2898DeriveBytes ("password", null, 5);
98                 }
99
100                 [Test]
101                 [ExpectedException (typeof (ArgumentOutOfRangeException))]
102                 public void ConstructorPasswordSaltIterationsZero () 
103                 {
104                         Rfc2898DeriveBytes pkcs5 = new Rfc2898DeriveBytes ("password", salt, 0);
105                 }
106
107                 [Test]
108                 [ExpectedException (typeof (ArgumentOutOfRangeException))]
109                 public void ConstructorPasswordSaltIterationsNegative () 
110                 {
111                         Rfc2898DeriveBytes pkcs5 = new Rfc2898DeriveBytes ("password", salt, Int32.MinValue);
112                 }
113
114                 [Test]
115                 public void ConstructorPasswordSaltLength () 
116                 {
117                         Rfc2898DeriveBytes pkcs5 = new Rfc2898DeriveBytes ("password", 8);
118                         AssertEquals ("IterationCount", 1000, pkcs5.IterationCount);
119                         AssertEquals ("Salt", 8, pkcs5.Salt.Length);
120                 }
121
122                 [Test]
123                 [ExpectedException (typeof (ArgumentNullException))]
124                 public void ConstructorPasswordNullSaltLength () 
125                 {
126                         Rfc2898DeriveBytes pkcs5 = new Rfc2898DeriveBytes (null, 8);
127                 }
128
129                 [Test]
130                 [ExpectedException (typeof (ArgumentException))]
131                 public void ConstructorPasswordSaltLengthZero () 
132                 {
133                         Rfc2898DeriveBytes pkcs5 = new Rfc2898DeriveBytes ("password", 0);
134                 }
135
136                 [Test]
137                 [ExpectedException (typeof (ArgumentOutOfRangeException))]
138                 public void ConstructorPasswordSaltLengthNegative () 
139                 {
140                         Rfc2898DeriveBytes pkcs5 = new Rfc2898DeriveBytes ("password", Int32.MinValue);
141                 }
142
143                 [Test]
144                 public void ConstructorPasswordSaltLengthIterations () 
145                 {
146                         Rfc2898DeriveBytes pkcs5 = new Rfc2898DeriveBytes ("password", 8, 5);
147                         AssertEquals ("IterationCount", 5, pkcs5.IterationCount);
148                         AssertEquals ("Salt", 8, pkcs5.Salt.Length);
149                 }
150
151                 [Test]
152                 [ExpectedException (typeof (ArgumentNullException))]
153                 public void ConstructorPasswordNullSaltLengthIterations () 
154                 {
155                         Rfc2898DeriveBytes pkcs5 = new Rfc2898DeriveBytes (null, 8, 5);
156                 }
157
158                 [Test]
159                 [ExpectedException (typeof (ArgumentException))]
160                 public void ConstructorPasswordSaltLengthZeroIterations () 
161                 {
162                         Rfc2898DeriveBytes pkcs5 = new Rfc2898DeriveBytes ("password", 0, 5);
163                 }
164
165                 [Test]
166                 [ExpectedException (typeof (ArgumentOutOfRangeException))]
167                 public void ConstructorPasswordSaltLengthNegativeIterations () 
168                 {
169                         Rfc2898DeriveBytes pkcs5 = new Rfc2898DeriveBytes ("password", Int32.MinValue, 5);
170                 }
171
172                 [Test]
173                 [ExpectedException (typeof (ArgumentOutOfRangeException))]
174                 public void ConstructorPasswordSaltLengthIterationsZero () 
175                 {
176                         Rfc2898DeriveBytes pkcs5 = new Rfc2898DeriveBytes ("password", 8, 0);
177                 }
178
179                 [Test]
180                 [ExpectedException (typeof (ArgumentOutOfRangeException))]
181                 public void ConstructorPasswordSaltLengthIterationsNegative () 
182                 {
183                         Rfc2898DeriveBytes pkcs5 = new Rfc2898DeriveBytes ("password", 8, Int32.MinValue);
184                 }
185
186                 [Test]
187                 public void IterationCount () 
188                 {
189                         Rfc2898DeriveBytes pkcs5 = new Rfc2898DeriveBytes ("password", salt, 5);
190                         AssertEquals ("IterationCount", 5, pkcs5.IterationCount);
191                         pkcs5.IterationCount = Int32.MaxValue;
192                         AssertEquals ("IterationCount", Int32.MaxValue, pkcs5.IterationCount);
193                 }
194
195                 [Test]
196                 public void SaltNew () 
197                 {
198                         Rfc2898DeriveBytes pkcs5 = new Rfc2898DeriveBytes ("password", salt);
199                         AssertEquals ("Salt", salt, pkcs5.Salt);
200                         byte[] newSalt = (byte[]) salt.Clone ();
201                         newSalt [0] = 0xFF;
202                         pkcs5.Salt = newSalt;
203                         AssertEquals ("Salt(new)", newSalt, pkcs5.Salt);
204                 }
205
206                 [Test]
207                 public void SaltCantModifyInternal () 
208                 {
209                         Rfc2898DeriveBytes pkcs5 = new Rfc2898DeriveBytes ("password", salt);
210                         AssertEquals ("Salt", salt, pkcs5.Salt);
211                         byte[] modSalt = (byte[]) salt.Clone ();
212                         modSalt [0] = 0xFF;
213                         Assert ("Can't modify internal salt", (BitConverter.ToString(pkcs5.Salt) != BitConverter.ToString(modSalt)));
214                 }
215
216                 [Test]
217                 [ExpectedException (typeof (ArgumentNullException))]
218                 public void SaltNull () 
219                 {
220                         Rfc2898DeriveBytes pkcs5 = new Rfc2898DeriveBytes ("password", salt);
221                         pkcs5.Salt = null;
222                 }
223
224                 [Test]
225                 [ExpectedException (typeof (ArgumentException))]
226                 public void SaltTooSmall () 
227                 {
228                         Rfc2898DeriveBytes pkcs5 = new Rfc2898DeriveBytes ("password", salt);
229                         byte[] smallSalt = { 0x01, 0x02, 0x03, 0x04, 0x05 };
230                         pkcs5.Salt = smallSalt;
231                 }
232
233                 [Test]
234                 [ExpectedException (typeof (ArgumentOutOfRangeException))]
235                 public void GetBytesZero ()
236                 {
237                         byte[] expected = { 0xd1, 0xda, 0xa7, 0x86, 0x15, 0xf2, 0x87, 0xe6 };
238                         Rfc2898DeriveBytes pkcs5 = new Rfc2898DeriveBytes ("password", salt, 5);
239                         byte[] key = pkcs5.GetBytes (0);
240                         AssertEquals ("GetBytesZero", 0, key.Length);
241                 }
242
243                 [Test]
244                 [ExpectedException (typeof (ArgumentOutOfRangeException))]
245                 public void GetBytesNegative () 
246                 {
247                         Rfc2898DeriveBytes pkcs5 = new Rfc2898DeriveBytes ("password", salt, 5);
248                         byte[] key = pkcs5.GetBytes (Int32.MinValue);
249                 }
250
251                 [Test]
252                 public void RFC3211_TC1 () 
253                 {
254                         byte[] expected = { 0xd1, 0xda, 0xa7, 0x86, 0x15, 0xf2, 0x87, 0xe6 };
255                         Rfc2898DeriveBytes pkcs5 = new Rfc2898DeriveBytes ("password", salt, 5);
256                         byte[] key = pkcs5.GetBytes (8);
257                         AssertEquals ("RFC3211_TC1", expected, key);
258                 }
259
260                 [Test]
261                 public void RFC3211_TC2 () 
262                 {
263                         byte[] expected = { 0x6A, 0x89, 0x70, 0xBF, 0x68, 0xC9, 0x2C, 0xAE, 0xA8, 0x4A, 0x8D, 0xF2, 0x85, 0x10, 0x85, 0x86 };
264                         Rfc2898DeriveBytes pkcs5 = new Rfc2898DeriveBytes ("All n-entities must communicate with other n-entities via n-1 entiteeheehees", salt, 500);
265                         byte[] key = pkcs5.GetBytes (16);
266                         AssertEquals ("RFC3211_TC2", expected, key);
267                 }
268
269                 [Test]
270                 public void RFC3211_TC2_TwoBlocks () 
271                 {
272                         byte[] expected = { 0x6A, 0x89, 0x70, 0xBF, 0x68, 0xC9, 0x2C, 0xAE, 0xA8, 0x4A, 0x8D, 0xF2, 0x85, 0x10, 0x85, 0x86, 0x07, 0x12, 0x63, 0x80, 0xcc, 0x47, 0xab, 0x2d, 0xa6, 0xcc, 0xda, 0xfb, 0x26, 0x83, 0xdf, 0xe8 };
273                         Rfc2898DeriveBytes pkcs5 = new Rfc2898DeriveBytes ("All n-entities must communicate with other n-entities via n-1 entiteeheehees", salt, 500);
274                         byte[] key = pkcs5.GetBytes (32);
275                         AssertEquals ("RFC3211_TC2_TwoBlocks", expected, key);
276                 }
277
278                 [Test]
279                 public void RFC3211_TC2_Splitted_OneBlock () 
280                 {
281                         Rfc2898DeriveBytes pkcs5 = new Rfc2898DeriveBytes ("All n-entities must communicate with other n-entities via n-1 entiteeheehees", salt, 500);
282                         byte[] key1 = pkcs5.GetBytes (8);
283                         byte[] expected_part1 = { 0x6A, 0x89, 0x70, 0xBF, 0x68, 0xC9, 0x2C, 0xAE };
284                         AssertEquals ("RFC3211_TC2_Splitted_OneBlock-1", expected_part1, key1);
285                         byte[] expected_part2 = { 0xA8, 0x4A, 0x8D, 0xF2, 0x85, 0x10, 0x85, 0x86 };
286                         byte[] key2 = pkcs5.GetBytes (8);
287                         AssertEquals ("RFC3211_TC2_Splitted_OneBlock-2", expected_part2, key2);
288                 }
289
290                 [Test]
291                 public void RFC3211_TC2_Splitted_TwoBlocks () 
292                 {
293                         Rfc2898DeriveBytes pkcs5 = new Rfc2898DeriveBytes ("All n-entities must communicate with other n-entities via n-1 entiteeheehees", salt, 500);
294                         byte[] key1 = pkcs5.GetBytes (16);
295                         byte[] expected_part1 = { 0x6A, 0x89, 0x70, 0xBF, 0x68, 0xC9, 0x2C, 0xAE, 0xA8, 0x4A, 0x8D, 0xF2, 0x85, 0x10, 0x85, 0x86 };
296                         AssertEquals ("RFC3211_TC2_Splitted_TwoBlocks-1", expected_part1, key1);
297                         byte[] expected_part2 = { 0x07, 0x12, 0x63, 0x80, 0xcc, 0x47, 0xab, 0x2d, 0xa6, 0xcc, 0xda, 0xfb, 0x26, 0x83, 0xdf, 0xe8 };
298                         byte[] key2 = pkcs5.GetBytes (16);
299                         AssertEquals ("RFC3211_TC2_Splitted_TwoBlocks-2", expected_part2, key2);
300                 }
301
302                 [Test]
303                 public void RFC3211_TC2_Reset () 
304                 {
305                         byte[] expected = { 0x6A, 0x89, 0x70, 0xBF, 0x68, 0xC9, 0x2C, 0xAE };
306                         Rfc2898DeriveBytes pkcs5 = new Rfc2898DeriveBytes ("All n-entities must communicate with other n-entities via n-1 entiteeheehees", salt, 500);
307                         byte[] key1 = pkcs5.GetBytes (8);
308                         AssertEquals ("RFC3211_TC2_part1", expected, key1);
309                         pkcs5.Reset ();
310                         byte[] key2 = pkcs5.GetBytes (8);
311                         AssertEquals ("RFC3211_TC2_part2", expected, key2);
312                 }
313         }
314 }
315
316 #endif