2004-03-28 Sebastien Pouliot <sebastien@ximian.com>
[mono.git] / mcs / class / corlib / Test / System.Security.Cryptography / DESTest.cs
1 //
2 // TestSuite.System.Security.Cryptography.DESTest.cs
3 //
4 // Author:
5 //      Sebastien Pouliot  <sebastien@ximian.com>
6 //
7 // (C) 2004 Novell (http://www.novell.com)
8 //
9
10 using System;
11 using System.Security.Cryptography;
12 using System.Text;
13
14 using NUnit.Framework;
15
16 namespace MonoTests.System.Security.Cryptography {
17
18         [TestFixture]
19         public class DESTest : Assertion {
20
21                 static byte[] wk1 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
22                 static byte[] wk2 = { 0x1E, 0x1E, 0x1E, 0x1E, 0x0F, 0x0F, 0x0F, 0x0F };
23                 static byte[] wk3 = { 0xE1, 0xE1, 0xE1, 0xE1, 0xF0, 0xF0, 0xF0, 0xF0 };
24                 static byte[] wk4 = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
25
26                 // parity adjusted
27                 static byte[] wk1p = { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 };
28                 static byte[] wk2p = { 0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E };
29                 static byte[] wk3p = { 0xE0, 0xE0, 0xE0, 0xE0, 0xF1, 0xF1, 0xF1, 0xF1 };
30                 static byte[] wk4p = { 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE };
31
32                 [Test]
33                 public void WeakKeys_WithoutParity () 
34                 {
35                         Assert ("WK-1", DES.IsWeakKey (wk1));
36                         Assert ("WK-2", DES.IsWeakKey (wk2));
37                         Assert ("WK-3", DES.IsWeakKey (wk3));
38                         Assert ("WK-4", DES.IsWeakKey (wk4));
39                 }
40
41                 [Test]
42                 public void WeakKeys_WithParity () 
43                 {
44                         Assert ("WK-1P", DES.IsWeakKey (wk1p));
45                         Assert ("WK-2P", DES.IsWeakKey (wk2p));
46                         Assert ("WK-3P", DES.IsWeakKey (wk3p));
47                         Assert ("WK-4P", DES.IsWeakKey (wk4p));
48                 }
49
50                 [Test]
51                 [ExpectedException (typeof (CryptographicException))]
52                 public void IsWeakKey_WrongKeyLength () 
53                 {
54                         byte[] key = new byte [16]; // 128 bits
55                         DES.IsWeakKey (key);
56                 }
57
58                 [Test]
59                 [ExpectedException (typeof (NullReferenceException))]
60                 public void IsWeakKey_Null () 
61                 {
62                         DES.IsWeakKey (null);
63                 }
64
65                 static byte[] swk1   = { 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF };
66                 static byte[] swk2   = { 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00 };
67                 static byte[] swk3   = { 0x1E, 0xE1, 0x1E, 0xE1, 0x0F, 0xF0, 0x0F, 0xF0 };
68                 static byte[] swk4   = { 0xE1, 0x1E, 0xE1, 0x1E, 0xF0, 0x0F, 0xF0, 0x0F };
69                 static byte[] swk5   = { 0x00, 0xE1, 0x00, 0xE1, 0x00, 0xF0, 0x00, 0xF0 };
70                 static byte[] swk6   = { 0xE1, 0x00, 0xE1, 0x00, 0xF0, 0x00, 0xF0, 0x00 };
71                 static byte[] swk7   = { 0x1E, 0xFF, 0x1E, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF };
72                 static byte[] swk8   = { 0xFF, 0x1E, 0xFF, 0x1E, 0xFF, 0x0F, 0xFF, 0x0F };
73                 static byte[] swk9   = { 0x00, 0x1E, 0x00, 0x1E, 0x00, 0x0F, 0x00, 0x0F };
74                 static byte[] swk10  = { 0x1E, 0x00, 0x1E, 0x00, 0x0F, 0x00, 0x0F, 0x00 };
75                 static byte[] swk11  = { 0xE1, 0xFF, 0xE1, 0xFF, 0xF0, 0xFF, 0xF0, 0xFF };
76                 static byte[] swk12  = { 0xFF, 0xE1, 0xFF, 0xE1, 0xFF, 0xF0, 0xFF, 0xF0 };
77
78                 static byte[] swk1p  = { 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE };
79                 static byte[] swk2p  = { 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01 };
80                 static byte[] swk3p  = { 0x1F, 0xE0, 0x1F, 0xE0, 0x0E, 0xF1, 0x0E, 0xF1 };
81                 static byte[] swk4p  = { 0xE0, 0x1F, 0xE0, 0x1F, 0xF1, 0x0E, 0xF1, 0x0E };
82                 static byte[] swk5p  = { 0x01, 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1 };
83                 static byte[] swk6p  = { 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1, 0x01 };
84                 static byte[] swk7p  = { 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E, 0xFE };
85                 static byte[] swk8p  = { 0xFE, 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E };
86                 static byte[] swk9p  = { 0x01, 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E };
87                 static byte[] swk10p = { 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E, 0x01 };
88                 static byte[] swk11p = { 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE };
89                 static byte[] swk12p = { 0xFE, 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1 };
90
91                 [Test]
92                 public void SemiWeakKeys_WithoutParity () 
93                 {
94                         Assert ("SWK-01", DES.IsSemiWeakKey (swk1));
95                         Assert ("SWK-02", DES.IsSemiWeakKey (swk2));
96                         Assert ("SWK-03", DES.IsSemiWeakKey (swk3));
97                         Assert ("SWK-04", DES.IsSemiWeakKey (swk4));
98                         Assert ("SWK-05", DES.IsSemiWeakKey (swk5));
99                         Assert ("SWK-06", DES.IsSemiWeakKey (swk6));
100                         Assert ("SWK-07", DES.IsSemiWeakKey (swk7));
101                         Assert ("SWK-08", DES.IsSemiWeakKey (swk8));
102                         Assert ("SWK-09", DES.IsSemiWeakKey (swk9));
103                         Assert ("SWK-10", DES.IsSemiWeakKey (swk10));
104                         Assert ("SWK-11", DES.IsSemiWeakKey (swk11));
105                         Assert ("SWK-12", DES.IsSemiWeakKey (swk12));
106                 }
107
108                 [Test]
109                 public void SemiWeakKeys_WithParity () 
110                 {
111                         Assert ("SWK-01P", DES.IsSemiWeakKey (swk1p));
112                         Assert ("SWK-02P", DES.IsSemiWeakKey (swk2p));
113                         Assert ("SWK-03P", DES.IsSemiWeakKey (swk3p));
114                         Assert ("SWK-04P", DES.IsSemiWeakKey (swk4p));
115                         Assert ("SWK-05P", DES.IsSemiWeakKey (swk5p));
116                         Assert ("SWK-06P", DES.IsSemiWeakKey (swk6p));
117                         Assert ("SWK-07P", DES.IsSemiWeakKey (swk7p));
118                         Assert ("SWK-08P", DES.IsSemiWeakKey (swk8p));
119                         Assert ("SWK-09P", DES.IsSemiWeakKey (swk9p));
120                         Assert ("SWK-10P", DES.IsSemiWeakKey (swk10p));
121                         Assert ("SWK-11P", DES.IsSemiWeakKey (swk11p));
122                         Assert ("SWK-12P", DES.IsSemiWeakKey (swk12p));
123                 }
124
125                 [Test]
126                 [ExpectedException (typeof (CryptographicException))]
127                 public void IsSemiWeakKey_WrongKeyLength () 
128                 {
129                         byte[] key = new byte [16]; // 128 bits
130                         DES.IsSemiWeakKey (key);
131                 }
132
133                 [Test]
134                 [ExpectedException (typeof (NullReferenceException))]
135                 public void IsSemiWeakKey_Null () 
136                 {
137                         DES.IsSemiWeakKey (null);
138                 }
139
140                 [Test]
141                 public void GetKey () 
142                 {
143                         DES des = DES.Create ();
144                         byte[] key = des.Key;
145                         AssertEquals ("64 bits", 8, key.Length);
146
147                         // we get a copy of the key (not the original)
148                         string s = BitConverter.ToString (key);
149                         des.Clear ();
150                         AssertEquals ("Copy", s, BitConverter.ToString (key));
151                 }
152
153                 [Test]
154                 [ExpectedException (typeof (ArgumentNullException))]
155                 public void SetKey_Null () 
156                 {
157                         DES des = DES.Create ();
158                         des.Key = null;
159                 }
160
161                 [Test]
162                 [ExpectedException (typeof (ArgumentException))]
163                 public void SetKey_WrongLength () 
164                 {
165                         DES des = DES.Create ();
166                         des.Key = new byte [16]; // 128 bits
167                 }
168
169                 [Test]
170                 [ExpectedException (typeof (CryptographicException))]
171                 public void SetKey_Weak () 
172                 {
173                         DES des = DES.Create ();
174                         des.Key = wk1;
175                 }
176
177                 [Test]
178                 [ExpectedException (typeof (CryptographicException))]
179                 public void SetKey_SemiWeak () 
180                 {
181                         DES des = DES.Create ();
182                         des.Key = swk1;
183                 }
184         }
185
186         // Test vectors from FIPS 81 - DES Modes of Operations
187         // http://csrc.nist.gov/publications/fips/fips81/fips81.htm
188         //
189         // Note: they are to be called from specifics implementations -
190         //   not for the abstract DES. Thats why they are in a separate class
191         //   which doesn't have a [TestFixture] attribute
192         public class DESFIPS81Test : Assertion {
193                 protected DES des;
194
195                 // Table B1 - ECB Mode
196                 [Test]
197                 public void FIPS81_ECBMode () 
198                 {
199                         byte[] plaintext = Encoding.ASCII.GetBytes ("Now is the time for all ");
200                         byte[] result = new byte [24];
201
202                         des.Key = new byte[] { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF };
203                         des.Mode = CipherMode.ECB;
204                         des.Padding = PaddingMode.None;
205                         ICryptoTransform encrypt = des.CreateEncryptor ();
206
207                         encrypt.TransformBlock (plaintext, 0, 8, result, 0);
208                         AssertEquals ("Encrypt Block 1", "3F-A4-0E-8A-98-4D-48-15", BitConverter.ToString (result, 0, 8));
209
210                         encrypt.TransformBlock (plaintext, 8, 8, result, 8);
211                         AssertEquals ("Encrypt Block 2", "6A-27-17-87-AB-88-83-F9", BitConverter.ToString (result, 8, 8));
212
213                         encrypt.TransformBlock (plaintext, 16, 8, result, 16);
214                         AssertEquals ("Encrypt Block 3", "89-3D-51-EC-4B-56-3B-53", BitConverter.ToString (result, 16, 8));
215
216                         ICryptoTransform decrypt = des.CreateDecryptor ();
217                         
218                         byte[] decrypted = new byte [24]; // MS cannot *always* reuse buffers
219                         decrypt.TransformBlock (result, 0, 8, decrypted, 0);
220                         AssertEquals ("Decrypt Block 1", "Now is t", Encoding.ASCII.GetString (decrypted, 0, 8));
221
222                         decrypt.TransformBlock (result, 8, 8, decrypted, 8);
223                         AssertEquals ("Decrypt Block 2", "he time ", Encoding.ASCII.GetString (decrypted, 8, 8));
224
225                         decrypt.TransformBlock (result, 16, 8, decrypted, 16);
226                         AssertEquals ("Decrypt Block 3", "for all ", Encoding.ASCII.GetString (decrypted, 16, 8));
227                 }
228
229                 // Table C1 - CBC Mode
230                 [Test]
231                 public void FIPS81_CBCMode () 
232                 {
233                         byte[] plaintext = Encoding.ASCII.GetBytes ("Now is the time for all ");
234                         byte[] result = new byte [24];
235
236                         des.Key = new byte[] { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF };
237                         des.IV = new byte[] { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF };
238                         des.Mode = CipherMode.CBC;
239                         des.Padding = PaddingMode.None;
240                         ICryptoTransform encrypt = des.CreateEncryptor ();
241
242                         encrypt.TransformBlock (plaintext, 0, 8, result, 0);
243                         AssertEquals ("Encrypt Block 1", "E5-C7-CD-DE-87-2B-F2-7C", BitConverter.ToString (result, 0, 8));
244
245                         encrypt.TransformBlock (plaintext, 8, 8, result, 8);
246                         AssertEquals ("Encrypt Block 2", "43-E9-34-00-8C-38-9C-0F", BitConverter.ToString (result, 8, 8));
247
248                         byte[] final = encrypt.TransformFinalBlock (plaintext, 16, 8);
249                         Buffer.BlockCopy (final, 0, result, 16, 8);
250                         AssertEquals ("Encrypt Block 3", "68-37-88-49-9A-7C-05-F6", BitConverter.ToString (result, 16, 8));
251
252                         ICryptoTransform decrypt = des.CreateDecryptor ();
253                         
254                         decrypt.TransformBlock (result, 0, 8, result, 0);
255                         AssertEquals ("Decrypt Block 1", "Now is t", Encoding.ASCII.GetString (result, 0, 8));
256
257                         decrypt.TransformBlock (result, 8, 8, result, 8);
258                         AssertEquals ("Decrypt Block 2", "he time ", Encoding.ASCII.GetString (result, 8, 8));
259
260                         final = decrypt.TransformFinalBlock (result, 16, 8);
261                         AssertEquals ("Decrypt Block 3", "for all ", Encoding.ASCII.GetString (final));
262                 }
263
264                 // Table D2 - CFB Mode 8 bits
265                 [Test]
266                 public void FIPS81_CFB8Mode () 
267                 {
268                         byte[] plaintext = Encoding.ASCII.GetBytes ("Now is theXXXXXX"); // padding
269                         byte[] result = new byte [16];
270
271                         des.Key = new byte[] { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF };
272                         des.IV = new byte[] { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF };
273                         des.Mode = CipherMode.CFB;
274                         des.Padding = PaddingMode.None;
275                         des.FeedbackSize = 8;
276                         ICryptoTransform encrypt = des.CreateEncryptor ();
277
278                         encrypt.TransformBlock (plaintext, 0, 8, result, 0);
279                         AssertEquals ("Encrypt Block 1", "F3-1F-DA-07-01-14-62-EE", BitConverter.ToString (result, 0, 8));
280
281                         byte[] final = encrypt.TransformFinalBlock (plaintext, 8, 8);
282                         Buffer.BlockCopy (final, 0, result, 8, 8);
283                         AssertEquals ("Encrypt Block 2", "18-7F", BitConverter.ToString (final).Substring (0, 5));
284
285                         ICryptoTransform decrypt = des.CreateDecryptor ();
286                         
287                         decrypt.TransformBlock (result, 0, 8, result, 0);
288                         AssertEquals ("Decrypt Block 1", "Now is t", Encoding.ASCII.GetString (result, 0, 8));
289
290                         final = decrypt.TransformFinalBlock (result, 8, 8);
291                         AssertEquals ("Decrypt Block 2", "he", Encoding.ASCII.GetString (final, 0, 2));
292                 }
293         }
294 }