* roottypes.cs: Rename from tree.cs.
[mono.git] / mcs / class / Mono.Security / Test / Mono.Security.Cryptography / ARC4ManagedTest.cs
1 //
2 // ARC4ManagedTest.cs - NUnit Test Cases for Alleged RC4(tm)
3 //      RC4 is a trademark of RSA Security
4 //
5 // Author:
6 //      Sebastien Pouliot (spouliot@motus.com)
7 //
8 // (C) 2003 Motus Technologies Inc. (http://www.motus.com)
9 //
10
11 using NUnit.Framework;
12 using System;
13 using System.Security.Cryptography;
14 using Mono.Security.Cryptography;
15
16 namespace MonoTests.Mono.Security.Cryptography {
17
18         // References
19         // a.   Usenet 1994 - RC4 Algorithm revealed
20         //      http://www.qrst.de/html/dsds/rc4.htm
21         // b.   Netscape SSL version 3 implementation details
22         //      Export Client SSL Connection Details
23         //      http://wp.netscape.com/eng/ssl3/traces/trc-clnt-ex.html
24
25         [TestFixture]
26         public class ARC4ManagedTest : Assertion {
27
28                 // because most crypto stuff works with byte[] buffers
29                 static public void AssertEquals (string msg, byte[] array1, byte[] array2) 
30                 {
31                         if ((array1 == null) && (array2 == null))
32                                 return;
33                         if (array1 == null)
34                                 Fail (msg + " -> First array is NULL");
35                         if (array2 == null)
36                                 Fail (msg + " -> Second array is NULL");
37                 
38                         bool a = (array1.Length == array2.Length);
39                         if (a) {
40                                 for (int i = 0; i < array1.Length; i++) {
41                                         if (array1 [i] != array2 [i]) {
42                                                 a = false;
43                                                 break;
44                                         }
45                                 }
46                         }
47                         msg += " -> Expected " + BitConverter.ToString (array1, 0);
48                         msg += " is different than " + BitConverter.ToString (array2, 0);
49                         Assert (msg, a);
50                 }
51
52                 // from ref. a
53                 [Test]
54                 public void Vector0 () 
55                 {
56                         byte[] key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef };
57                         byte[] input = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef };
58                         byte[] expected = { 0x75, 0xb7, 0x87, 0x80, 0x99, 0xe0, 0xc5, 0x96 };
59                         ARC4Managed rc4 = new ARC4Managed ();
60                         rc4.Key = key;
61                         ICryptoTransform stream = rc4.CreateEncryptor ();
62                         byte[] output = stream.TransformFinalBlock (input, 0, input.Length);
63                         AssertEquals ("RC4 - Test Vector 0", expected, output);
64                 }
65
66                 // from ref. a
67                 [Test]
68                 public void Vector1 () 
69                 {
70                         byte[] key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef };
71                         byte[] input = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
72                         byte[] expected = { 0x74, 0x94, 0xc2, 0xe7, 0x10, 0x4b, 0x08, 0x79 };
73                         ARC4Managed rc4 = new ARC4Managed ();
74                         rc4.Key = key;
75                         ICryptoTransform stream = rc4.CreateEncryptor ();
76                         byte[] output = stream.TransformFinalBlock (input, 0, input.Length);
77                         AssertEquals ("RC4 - Test Vector 1", expected, output);
78                 }
79
80                 // from ref. a
81                 [Test]
82                 public void Vector2 () 
83                 {
84                         byte[] key = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
85                         byte[] input = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
86                         byte[] expected = { 0xde, 0x18, 0x89, 0x41, 0xa3, 0x37, 0x5d, 0x3a };
87                         ARC4Managed rc4 = new ARC4Managed ();
88                         rc4.Key = key;
89                         ICryptoTransform stream = rc4.CreateEncryptor ();
90                         byte[] output = stream.TransformFinalBlock (input, 0, input.Length);
91                         AssertEquals ("RC4 - Test Vector 2", expected, output);
92                 }
93
94                 // from ref. a
95                 [Test]
96                 public void Vector3 () 
97                 {
98                         byte[] key = { 0xef, 0x01, 0x23, 0x45 };
99                         byte[] input = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
100                         byte[] expected = { 0xd6, 0xa1, 0x41, 0xa7, 0xec, 0x3c, 0x38, 0xdf, 0xbd, 0x61 };
101                         ARC4Managed rc4 = new ARC4Managed ();
102                         rc4.Key = key;
103                         ICryptoTransform stream = rc4.CreateEncryptor ();
104                         byte[] output = stream.TransformFinalBlock (input, 0, input.Length);
105                         AssertEquals ("RC4 - Test Vector 3", expected, output);
106                 }
107
108                 // from ref. a
109                 [Test]
110                 public void Vector4 () 
111                 {
112                         byte[] key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef };
113                         byte[] input = new byte [512];
114                         for (int i=0; i < input.Length; i++)
115                                 input [i] = 0x01;
116                         byte[] expected = { 0x75, 0x95, 0xc3, 0xe6, 0x11, 0x4a, 0x09, 0x78, 0x0c, 0x4a, 0xd4, 
117                                 0x52, 0x33, 0x8e, 0x1f, 0xfd, 0x9a, 0x1b, 0xe9, 0x49, 0x8f, 
118                                 0x81, 0x3d, 0x76, 0x53, 0x34, 0x49, 0xb6, 0x77, 0x8d, 0xca, 
119                                 0xd8, 0xc7, 0x8a, 0x8d, 0x2b, 0xa9, 0xac, 0x66, 0x08, 0x5d, 
120                                 0x0e, 0x53, 0xd5, 0x9c, 0x26, 0xc2, 0xd1, 0xc4, 0x90, 0xc1, 
121                                 0xeb, 0xbe, 0x0c, 0xe6, 0x6d, 0x1b, 0x6b, 0x1b, 0x13, 0xb6, 
122                                 0xb9, 0x19, 0xb8, 0x47, 0xc2, 0x5a, 0x91, 0x44, 0x7a, 0x95, 
123                                 0xe7, 0x5e, 0x4e, 0xf1, 0x67, 0x79, 0xcd, 0xe8, 0xbf, 0x0a, 
124                                 0x95, 0x85, 0x0e, 0x32, 0xaf, 0x96, 0x89, 0x44, 0x4f, 0xd3, 
125                                 0x77, 0x10, 0x8f, 0x98, 0xfd, 0xcb, 0xd4, 0xe7, 0x26, 0x56, 
126                                 0x75, 0x00, 0x99, 0x0b, 0xcc, 0x7e, 0x0c, 0xa3, 0xc4, 0xaa, 
127                                 0xa3, 0x04, 0xa3, 0x87, 0xd2, 0x0f, 0x3b, 0x8f, 0xbb, 0xcd, 
128                                 0x42, 0xa1, 0xbd, 0x31, 0x1d, 0x7a, 0x43, 0x03, 0xdd, 0xa5, 
129                                 0xab, 0x07, 0x88, 0x96, 0xae, 0x80, 0xc1, 0x8b, 0x0a, 0xf6, 
130                                 0x6d, 0xff, 0x31, 0x96, 0x16, 0xeb, 0x78, 0x4e, 0x49, 0x5a, 
131                                 0xd2, 0xce, 0x90, 0xd7, 0xf7, 0x72, 0xa8, 0x17, 0x47, 0xb6, 
132                                 0x5f, 0x62, 0x09, 0x3b, 0x1e, 0x0d, 0xb9, 0xe5, 0xba, 0x53, 
133                                 0x2f, 0xaf, 0xec, 0x47, 0x50, 0x83, 0x23, 0xe6, 0x71, 0x32, 
134                                 0x7d, 0xf9, 0x44, 0x44, 0x32, 0xcb, 0x73, 0x67, 0xce, 0xc8, 
135                                 0x2f, 0x5d, 0x44, 0xc0, 0xd0, 0x0b, 0x67, 0xd6, 0x50, 0xa0, 
136                                 0x75, 0xcd, 0x4b, 0x70, 0xde, 0xdd, 0x77, 0xeb, 0x9b, 0x10, 
137                                 0x23, 0x1b, 0x6b, 0x5b, 0x74, 0x13, 0x47, 0x39, 0x6d, 0x62, 
138                                 0x89, 0x74, 0x21, 0xd4, 0x3d, 0xf9, 0xb4, 0x2e, 0x44, 0x6e, 
139                                 0x35, 0x8e, 0x9c, 0x11, 0xa9, 0xb2, 0x18, 0x4e, 0xcb, 0xef, 
140                                 0x0c, 0xd8, 0xe7, 0xa8, 0x77, 0xef, 0x96, 0x8f, 0x13, 0x90, 
141                                 0xec, 0x9b, 0x3d, 0x35, 0xa5, 0x58, 0x5c, 0xb0, 0x09, 0x29, 
142                                 0x0e, 0x2f, 0xcd, 0xe7, 0xb5, 0xec, 0x66, 0xd9, 0x08, 0x4b, 
143                                 0xe4, 0x40, 0x55, 0xa6, 0x19, 0xd9, 0xdd, 0x7f, 0xc3, 0x16, 
144                                 0x6f, 0x94, 0x87, 0xf7, 0xcb, 0x27, 0x29, 0x12, 0x42, 0x64, 
145                                 0x45, 0x99, 0x85, 0x14, 0xc1, 0x5d, 0x53, 0xa1, 0x8c, 0x86, 
146                                 0x4c, 0xe3, 0xa2, 0xb7, 0x55, 0x57, 0x93, 0x98, 0x81, 0x26, 
147                                 0x52, 0x0e, 0xac, 0xf2, 0xe3, 0x06, 0x6e, 0x23, 0x0c, 0x91, 
148                                 0xbe, 0xe4, 0xdd, 0x53, 0x04, 0xf5, 0xfd, 0x04, 0x05, 0xb3, 
149                                 0x5b, 0xd9, 0x9c, 0x73, 0x13, 0x5d, 0x3d, 0x9b, 0xc3, 0x35, 
150                                 0xee, 0x04, 0x9e, 0xf6, 0x9b, 0x38, 0x67, 0xbf, 0x2d, 0x7b, 
151                                 0xd1, 0xea, 0xa5, 0x95, 0xd8, 0xbf, 0xc0, 0x06, 0x6f, 0xf8, 
152                                 0xd3, 0x15, 0x09, 0xeb, 0x0c, 0x6c, 0xaa, 0x00, 0x6c, 0x80, 
153                                 0x7a, 0x62, 0x3e, 0xf8, 0x4c, 0x3d, 0x33, 0xc1, 0x95, 0xd2, 
154                                 0x3e, 0xe3, 0x20, 0xc4, 0x0d, 0xe0, 0x55, 0x81, 0x57, 0xc8, 
155                                 0x22, 0xd4, 0xb8, 0xc5, 0x69, 0xd8, 0x49, 0xae, 0xd5, 0x9d, 
156                                 0x4e, 0x0f, 0xd7, 0xf3, 0x79, 0x58, 0x6b, 0x4b, 0x7f, 0xf6, 
157                                 0x84, 0xed, 0x6a, 0x18, 0x9f, 0x74, 0x86, 0xd4, 0x9b, 0x9c, 
158                                 0x4b, 0xad, 0x9b, 0xa2, 0x4b, 0x96, 0xab, 0xf9, 0x24, 0x37, 
159                                 0x2c, 0x8a, 0x8f, 0xff, 0xb1, 0x0d, 0x55, 0x35, 0x49, 0x00, 
160                                 0xa7, 0x7a, 0x3d, 0xb5, 0xf2, 0x05, 0xe1, 0xb9, 0x9f, 0xcd, 
161                                 0x86, 0x60, 0x86, 0x3a, 0x15, 0x9a, 0xd4, 0xab, 0xe4, 0x0f, 
162                                 0xa4, 0x89, 0x34, 0x16, 0x3d, 0xdd, 0xe5, 0x42, 0xa6, 0x58, 
163                                 0x55, 0x40, 0xfd, 0x68, 0x3c, 0xbf, 0xd8, 0xc0, 0x0f, 0x12, 
164                                 0x12, 0x9a, 0x28, 0x4d, 0xea, 0xcc, 0x4c, 0xde, 0xfe, 0x58, 
165                                 0xbe, 0x71, 0x37, 0x54, 0x1c, 0x04, 0x71, 0x26, 0xc8, 0xd4, 
166                                 0x9e, 0x27, 0x55, 0xab, 0x18, 0x1a, 0xb7, 0xe9, 0x40, 0xb0, 
167                                 0xc0 };
168                         ARC4Managed rc4 = new ARC4Managed ();
169                         rc4.Key = key;
170                         ICryptoTransform stream = rc4.CreateEncryptor ();
171                         byte[] output = stream.TransformFinalBlock (input, 0, input.Length);
172                         AssertEquals ("RC4 - Test Vector 4", expected, output);
173                 }
174
175                 static byte[] clientWriteKey = { 0x32, 0x10, 0xcd, 0xe1, 0xd6, 0xdc, 0x07, 0x83, 0xf3, 0x75, 0x4c, 0x32, 0x2e, 0x59, 0x96, 0x61 };
176                 static byte[] serverWriteKey = { 0xed, 0x0e, 0x56, 0xc8, 0x95, 0x12, 0x37, 0xb6, 0x21, 0x17, 0x1c, 0x72, 0x79, 0x91, 0x12, 0x1e };
177
178                 // SSL3 Client's Finished Handshake (from ref. b)
179                 [Test]
180                 public void SSLClient () 
181                 {
182                         byte[] data = { 0x14, 0x00, 0x00, 0x24, 0xf2, 0x40, 0x10, 0x3f, 0x74, 0x63, 0xea, 0xe8, 0x7a, 0x27, 0x23, 0x56, 0x5f, 0x59, 0x07, 0xd2, 0xa3, 0x79, 0x5d, 0xb7, 0x8b, 0x94, 0xdb, 0xcf, 0xfa, 0xf5, 0x18, 0x22, 0x15, 0x7b, 0xf2, 0x4a, 0x96, 0x52, 0x9a, 0x0e, 0xd3, 0x09, 0xde, 0x28, 0x84, 0xa7, 0x07, 0x5c, 0x7c, 0x0c, 0x08, 0x85, 0x6b, 0x4f, 0x63, 0x04 };
183                         ARC4Managed rc4 = new ARC4Managed ();
184                         rc4.Key = clientWriteKey;
185                         // encrypt inplace (in same buffer)
186                         rc4.TransformBlock (data, 0, data.Length, data, 0); 
187                         byte[] expectedData = { 0xed, 0x37, 0x7f, 0x16, 0xd3, 0x11, 0xe8, 0xa3, 0xe1, 0x2a, 0x20, 0xb7, 0x88, 0xf6, 0x11, 0xf3, 0xa6, 0x7d, 0x37, 0xf7, 0x17, 0xac, 0x67, 0x20, 0xb8, 0x0e, 0x88, 0xd1, 0xa0, 0xc6, 0x83, 0xe4, 0x80, 0xe8, 0xc7, 0xe3, 0x0b, 0x91, 0x29, 0x30, 0x29, 0xe4, 0x28, 0x47, 0xb7, 0x40, 0xa4, 0xd1, 0x3c, 0xda, 0x82, 0xb7, 0xb3, 0x9f, 0x67, 0x10 };
188                         AssertEquals ("RC4 - Client's Finished Handshake", expectedData, data);
189                 }
190
191                 // SSL3 Server Finished Handshake (from ref. b)
192                 [Test]
193                 public void SSLServer () 
194                 {
195                         byte[] encryptedData = { 0x54, 0x3c, 0xe1, 0xe7, 0x4d, 0x77, 0x76, 0x62, 0x86, 0xfa, 0x4e, 0x0a, 0x6f, 0x5f, 0x6a, 0x3d, 0x43, 0x26, 0xf4, 0xad, 0x8d, 0x3e, 0x09, 0x0b, 0x2b, 0xf7, 0x9f, 0x49, 0x44, 0x92, 0xfb, 0xa9, 0xa4, 0xb0, 0x5a, 0xd8, 0x72, 0x77, 0x6e, 0x8b, 0xb3, 0x78, 0xfb, 0xda, 0xe0, 0x25, 0xef, 0xb3, 0xf5, 0xa7, 0x90, 0x08, 0x6d, 0x60, 0xd5, 0x4e };
196                         ARC4Managed rc4 = new ARC4Managed ();
197                         rc4.Key = serverWriteKey;
198                         // decrypt inplace (in same buffer)
199                         rc4.TransformBlock (encryptedData, 0, encryptedData.Length, encryptedData, 0); 
200                         byte[] expectedData = { 0x14, 0x00, 0x00, 0x24, 0xb7, 0xcc, 0xd6, 0x05, 0x6b, 0xfc, 0xfa, 0x6d, 0xfa, 0xdd, 0x76, 0x81, 0x45, 0x36, 0xe4, 0xf4, 0x26, 0x35, 0x72, 0x2c, 0xec, 0x87, 0x62, 0x1f, 0x55, 0x08, 0x05, 0x4f, 0xc8, 0xf5, 0x7c, 0x49, 0xe2, 0xee, 0xc5, 0xba, 0xbd, 0x69, 0x27, 0x3b, 0xd0, 0x13, 0x23, 0x52, 0xed, 0xec, 0x11, 0x55, 0xd8, 0xb9, 0x90, 0x8c };
201                         AssertEquals ("RC4 - Server's Finished Handshake", expectedData, encryptedData);
202                 }
203                 
204                 [Test]
205                 public void DefaultProperties () 
206                 {
207                         ARC4Managed rc4 = new ARC4Managed ();
208                         Assert ("CanReuseTransform", !rc4.CanReuseTransform);
209                         Assert ("CanTransformMultipleBlocks", rc4.CanTransformMultipleBlocks);
210                         AssertEquals ("InputBlockSize", 1, rc4.InputBlockSize);
211                         AssertEquals ("OutputBlockSize", 1, rc4.OutputBlockSize);
212                 }
213                 
214                 [Test]
215                 public void DefaultSizes () 
216                 {
217                         ARC4Managed rc4 = new ARC4Managed ();
218                         rc4.GenerateKey ();
219                         rc4.GenerateIV ();
220                         AssertEquals ("Key.Length", 16, rc4.Key.Length);
221                         AssertEquals ("KeySize", 128, rc4.KeySize);
222                         AssertEquals ("IV.Length", 0, rc4.IV.Length);
223                 }
224
225                 [Test]
226                 [ExpectedException (typeof (ArgumentNullException))]
227                 public void TransformBlock_InputBuffer_Null () 
228                 {
229                         byte[] output = new byte [1];
230                         ARC4Managed rc4 = new ARC4Managed ();
231                         rc4.TransformBlock (null, 0, 1, output, 0); 
232                 }
233
234                 [Test]
235                 [ExpectedException (typeof (ArgumentOutOfRangeException))]
236                 public void TransformBlock_InputOffset_Negative () 
237                 {
238                         byte[] input = new byte [1];
239                         byte[] output = new byte [1];
240                         ARC4Managed rc4 = new ARC4Managed ();
241                         rc4.TransformBlock (input, -1, 1, output, 0); 
242                 }
243
244                 [Test]
245                 [ExpectedException (typeof (ArgumentException))]
246                 public void TransformBlock_InputOffset_Overflow () 
247                 {
248                         byte[] input = new byte [1];
249                         byte[] output = new byte [1];
250                         ARC4Managed rc4 = new ARC4Managed ();
251                         rc4.TransformBlock (input, Int32.MaxValue, 1, output, 0); 
252                 }
253
254                 [Test]
255                 [ExpectedException (typeof (ArgumentOutOfRangeException))]
256                 public void TransformBlock_InputCount_Negative () 
257                 {
258                         byte[] input = new byte [1];
259                         byte[] output = new byte [1];
260                         ARC4Managed rc4 = new ARC4Managed ();
261                         rc4.TransformBlock (input, 0, -1, output, 0); 
262                 }
263
264                 [Test]
265                 [ExpectedException (typeof (ArgumentException))]
266                 public void TransformBlock_InputCount_Overflow () 
267                 {
268                         byte[] input = new byte [1];
269                         byte[] output = new byte [1];
270                         ARC4Managed rc4 = new ARC4Managed ();
271                         rc4.TransformBlock (input, 1, Int32.MaxValue, output, 0); 
272                 }
273
274                 [Test]
275                 [ExpectedException (typeof (ArgumentNullException))]
276                 public void TransformBlock_OutputBuffer_Null () 
277                 {
278                         byte[] input = new byte [1];
279                         ARC4Managed rc4 = new ARC4Managed ();
280                         rc4.TransformBlock (input, 0, 1, null, 0); 
281                 }
282
283                 [Test]
284                 [ExpectedException (typeof (ArgumentOutOfRangeException))]
285                 public void TransformBlock_OutputOffset_Negative () 
286                 {
287                         byte[] input = new byte [1];
288                         byte[] output = new byte [1];
289                         ARC4Managed rc4 = new ARC4Managed ();
290                         rc4.TransformBlock (input, 0, 1, output, -1); 
291                 }
292
293                 [Test]
294                 [ExpectedException (typeof (ArgumentException))]
295                 public void TransformBlock_OutputOffset_Overflow () 
296                 {
297                         byte[] input = new byte [1];
298                         byte[] output = new byte [1];
299                         ARC4Managed rc4 = new ARC4Managed ();
300                         rc4.TransformBlock (input, 0, 1, output, Int32.MaxValue); 
301                 }
302
303                 [Test]
304                 [ExpectedException (typeof (ArgumentNullException))]
305                 public void TransformFinalBlock_InputBuffer_Null () 
306                 {
307                         ARC4Managed rc4 = new ARC4Managed ();
308                         rc4.TransformFinalBlock (null, 0, 1); 
309                 }
310
311                 [Test]
312                 [ExpectedException (typeof (ArgumentOutOfRangeException))]
313                 public void TransformFinalBlock_InputOffset_Negative () 
314                 {
315                         byte[] input = new byte [1];
316                         ARC4Managed rc4 = new ARC4Managed ();
317                         rc4.TransformFinalBlock (input, -1, 1); 
318                 }
319
320                 [Test]
321                 [ExpectedException (typeof (ArgumentException))]
322                 public void TransformFinalBlock_InputOffset_Overflow () 
323                 {
324                         byte[] input = new byte [1];
325                         ARC4Managed rc4 = new ARC4Managed ();
326                         rc4.TransformFinalBlock (input, Int32.MaxValue, 1); 
327                 }
328
329                 [Test]
330                 [ExpectedException (typeof (ArgumentOutOfRangeException))]
331                 public void TransformFinalBlock_InputCount_Negative () 
332                 {
333                         byte[] input = new byte [1];
334                         ARC4Managed rc4 = new ARC4Managed ();
335                         rc4.TransformFinalBlock (input, 0, -1); 
336                 }
337
338                 [Test]
339                 [ExpectedException (typeof (ArgumentException))]
340                 public void TransformFinalBlock_InputCount_Overflow () 
341                 {
342                         byte[] input = new byte [1];
343                         ARC4Managed rc4 = new ARC4Managed ();
344                         rc4.TransformFinalBlock (input, 1, Int32.MaxValue); 
345                 }
346         }
347 }