[jenkins] Make the concurrent GC the default on mainline archtectures.
[mono.git] / mcs / class / Mono.Security / Test / Mono.Security.Authenticode / PrivateKeyTest.cs
1 //
2 // PrivateKeyTest.cs - NUnit Test Cases for Private Key File
3 //
4 // Author:
5 //      Sebastien Pouliot (sebastien@ximian.com)
6 //      Bernie Solomon
7 //
8 // (C) 2003 Motus Technologies Inc. (http://www.motus.com)
9 // Copyright (C) 2004 Novell (http://www.novell.com)
10 //
11
12 using System;
13 using System.IO;
14 using System.Security.Cryptography;
15 using System.Text;
16
17 using Mono.Security.Authenticode;
18 using NUnit.Framework;
19
20 namespace MonoTests.Mono.Security.Authenticode {
21
22         // partial copy of /mcs/class/Mono.Security/Mono.Security/BitConverterLE.cs
23         internal sealed class BitConverterLE {
24
25                 private BitConverterLE ()
26                 {
27                 }
28
29                 unsafe private static byte[] GetUIntBytes (byte *bytes)
30                 {
31                         if (BitConverter.IsLittleEndian)
32                                 return new byte [] { bytes [0], bytes [1], bytes [2], bytes [3] };
33                         else
34                                 return new byte [] { bytes [3], bytes [2], bytes [1], bytes [0] };
35                 }
36
37                 unsafe internal static byte[] GetBytes (int value)
38                 {
39                         return GetUIntBytes ((byte *) &value);
40                 }
41
42                 unsafe private static void UIntFromBytes (byte *dst, byte[] src, int startIndex)
43                 {
44                         if (BitConverter.IsLittleEndian) {
45                                 dst [0] = src [startIndex];
46                                 dst [1] = src [startIndex + 1];
47                                 dst [2] = src [startIndex + 2];
48                                 dst [3] = src [startIndex + 3];
49                         } else {
50                                 dst [0] = src [startIndex + 3];
51                                 dst [1] = src [startIndex + 2];
52                                 dst [2] = src [startIndex + 1];
53                                 dst [3] = src [startIndex];
54                         }
55                 }
56
57                 unsafe internal static int ToInt32 (byte[] value, int startIndex)
58                 {
59                         int ret;
60
61                         UIntFromBytes ((byte *) &ret, value, startIndex);
62
63                         return ret;
64                 }
65         }
66
67 // HOWTO create a PVK file (on Windows using MS tools)
68 // makecert -n "CN=PVK1" -sv 1.pvk 1.cer
69
70 [TestFixture]
71 public class PrivateKeyTest : Assertion {
72
73         // because most crypto stuff works with byte[] buffers
74         static public void AssertEquals (string msg, byte[] array1, byte[] array2) 
75         {
76                 if ((array1 == null) && (array2 == null))
77                         return;
78                 if (array1 == null)
79                         Fail (msg + " -> First array is NULL");
80                 if (array2 == null)
81                         Fail (msg + " -> Second array is NULL");
82
83                 bool a = (array1.Length == array2.Length);
84                 if (a) {
85                         for (int i = 0; i < array1.Length; i++) {
86                                 if (array1 [i] != array2 [i]) {
87                                         a = false;
88                                         break;
89                                 }
90                         }
91                 }
92                 if (array1.Length > 0) {
93                         msg += " -> Expected " + BitConverter.ToString (array1, 0);
94                         msg += " is different than " + BitConverter.ToString (array2, 0);
95                 }
96                 Assert (msg, a);
97         }
98
99         string testfile;
100                 
101         [TestFixtureSetUp]
102         public void FixtureSetup ()
103         {
104                 testfile = Path.Combine (Path.GetTempPath (), "test.pvk");
105         }
106
107         [TearDown]
108         public void TearDown () 
109         {
110                 File.Delete (testfile);
111         }
112
113         private void WriteBuffer (byte[] buffer) 
114         {
115                 FileStream fs = File.Create (testfile);
116                 fs.Write (buffer, 0, buffer.Length);
117                 fs.Close ();
118         }
119
120         static byte[] nopwd = { 
121         0x1E, 0xF1, 0xB5, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 
122         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x01, 0x00, 0x00, 
123         0x07, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x52, 0x53, 0x41, 0x32, 
124         0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0xDB, 0x27, 0x34, 0xCB, 
125         0x3D, 0x27, 0xA0, 0x4F, 0x50, 0x68, 0xC7, 0x95, 0x4B, 0x7B, 0x69, 0xD1, 
126         0xFD, 0x30, 0x58, 0x72, 0x6B, 0xFF, 0x77, 0x64, 0x96, 0x35, 0x72, 0x36, 
127         0x98, 0xCE, 0x56, 0xDD, 0x94, 0x43, 0x7C, 0x0D, 0x61, 0x5C, 0x3A, 0xD6, 
128         0x1E, 0xD1, 0x89, 0x6C, 0xD5, 0x9B, 0x3E, 0xD3, 0x60, 0x3E, 0x28, 0x3F, 
129         0xC6, 0x51, 0x35, 0x0D, 0x4F, 0x7E, 0x79, 0xE6, 0xAE, 0xE4, 0xC8, 0xE9, 
130         0xA9, 0x14, 0x6E, 0xD2, 0xBD, 0x42, 0xB2, 0x14, 0x82, 0xEE, 0x26, 0x8F, 
131         0x21, 0x33, 0x1A, 0xD5, 0xD7, 0x6D, 0x90, 0xED, 0xC1, 0xA4, 0x1C, 0x84, 
132         0x3F, 0xA3, 0x8A, 0xFB, 0x33, 0x30, 0x32, 0xF6, 0xE3, 0xE6, 0xC8, 0x81, 
133         0x54, 0x88, 0x1A, 0x92, 0xF0, 0xBA, 0xB8, 0x4F, 0x52, 0x8D, 0xBD, 0x04, 
134         0x47, 0xBC, 0x55, 0xBC, 0xD0, 0x3D, 0x2C, 0x7F, 0x4F, 0xAB, 0x99, 0xDC, 
135         0xFB, 0x2D, 0x18, 0xF3, 0x99, 0x77, 0x10, 0x82, 0x48, 0xF3, 0xDE, 0x36, 
136         0xD7, 0x62, 0xA9, 0xCB, 0x58, 0x01, 0x97, 0x79, 0x66, 0x0D, 0x01, 0x1F, 
137         0xCC, 0x0B, 0xAB, 0x02, 0xA9, 0xE3, 0xF5, 0x85, 0xA8, 0x52, 0xBC, 0x10, 
138         0xD7, 0x90, 0x60, 0x60, 0x50, 0xB1, 0x08, 0x01, 0x85, 0x52, 0xAC, 0x05, 
139         0xF1, 0xCE, 0xF9, 0xE7, 0xBE, 0xDE, 0x46, 0x64, 0x40, 0xE5, 0x07, 0x82, 
140         0x20, 0xDD, 0x48, 0xF1, 0xE1, 0x85, 0x29, 0x8C, 0xFE, 0x57, 0x7C, 0x65, 
141         0xF5, 0x5C, 0x51, 0x9F, 0x63, 0xDE, 0xFC, 0x9C, 0xF9, 0x3F, 0x3D, 0xF2, 
142         0xDC, 0x9F, 0x65, 0x27, 0xEC, 0x50, 0x54, 0xB9, 0xCE, 0xF2, 0xC3, 0x10, 
143         0x93, 0x8B, 0xBE, 0x6A, 0xC1, 0x35, 0x19, 0xBB, 0x66, 0xA5, 0x5E, 0xEA, 
144         0x91, 0x1D, 0xFB, 0x26, 0xF8, 0x0F, 0x5C, 0x13, 0x73, 0xCC, 0x9A, 0x68, 
145         0x4C, 0x08, 0x9C, 0x02, 0xE5, 0xD5, 0x91, 0x37, 0x13, 0x68, 0x3D, 0xFC, 
146         0x3E, 0xA7, 0x43, 0x94, 0xBC, 0xFC, 0x4F, 0xB1, 0x8E, 0xC5, 0x5F, 0x24, 
147         0x9A, 0x6C, 0xDB, 0xC2, 0x49, 0x91, 0xEC, 0x2B, 0xB9, 0x3D, 0x2B, 0x96, 
148         0xA3, 0x60, 0xE3, 0xA8, 0x8C, 0x28, 0xB7, 0x53 };
149
150         [Test]
151         public void MSNoPassword ()
152         {
153                 WriteBuffer (nopwd);
154                 PrivateKey pvk = PrivateKey.CreateFromFile (testfile);
155                 AssertNotNull ("msnopwd.RSA", pvk.RSA);
156                 Assert ("msnopwd.Encrypted", !pvk.Encrypted);
157                 Assert ("msnopwd.Weak", pvk.Weak);
158                 AssertEquals ("msnopwd.KeyType", 2, pvk.KeyType);
159         }
160
161         // this will convert a PVK file without a password to a PVK file
162         // with a password (weak)
163         [Test]
164         public void ConvertToPasswordWeak () 
165         {
166                 WriteBuffer (nopwd);
167                 PrivateKey pvk = PrivateKey.CreateFromFile (testfile);
168                 string rsa1 = pvk.RSA.ToXmlString (true);
169                 pvk.Save (testfile, "password");
170                 pvk = PrivateKey.CreateFromFile (testfile, "password");
171                 AssertNotNull ("topwd.RSA", pvk.RSA);
172                 string rsa2 = pvk.RSA.ToXmlString (true);
173                 AssertEquals ("topwd.RSA identical", rsa1, rsa2);
174                 Assert ("topwd.Encrypted", pvk.Encrypted);
175                 Assert ("topwd.Weak", pvk.Weak);
176         }
177
178         // this will convert a PVK file without a password to a PVK file
179         // with a password (strong)
180         [Test]
181         public void ConvertToPasswordStrong () 
182         {
183                 WriteBuffer (nopwd);
184                 PrivateKey pvk = PrivateKey.CreateFromFile (testfile);
185                 string rsa1 = pvk.RSA.ToXmlString (true);
186                 pvk.Weak = false; // we want strong crypto
187                 pvk.Save (testfile, "password");
188                 pvk = PrivateKey.CreateFromFile (testfile, "password");
189                 AssertNotNull ("topwd.RSA", pvk.RSA);
190                 string rsa2 = pvk.RSA.ToXmlString (true);
191                 AssertEquals ("topwd.RSA identical", rsa1, rsa2);
192                 Assert ("topwd.Encrypted", pvk.Encrypted);
193                 Assert ("topwd.Weak", !pvk.Weak);
194         }
195
196         static byte[] pwd = { 
197         0x1E, 0xF1, 0xB5, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 
198         0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x34, 0x01, 0x00, 0x00, 
199         0x37, 0x53, 0x7C, 0x99, 0x01, 0xB5, 0x50, 0xF3, 0x79, 0x6E, 0xDE, 0xD5, 
200         0x8A, 0x1B, 0xED, 0x05, 0x07, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 
201         0x33, 0x98, 0xE8, 0x81, 0xA2, 0x9A, 0xEB, 0x36, 0xEF, 0x1B, 0x52, 0xFD, 
202         0xC3, 0x9B, 0xB7, 0x32, 0x02, 0xC0, 0x9F, 0xE0, 0x6A, 0x50, 0x81, 0x61, 
203         0x37, 0xBE, 0xEC, 0x1B, 0xC3, 0x34, 0x7B, 0x03, 0x0B, 0xC8, 0x31, 0x7B, 
204         0x0D, 0xA6, 0x7A, 0x05, 0xEA, 0xD1, 0xCA, 0x9A, 0xF3, 0x71, 0x84, 0x77, 
205         0x9E, 0x6F, 0xD1, 0xD0, 0xA0, 0x62, 0xFF, 0x3D, 0x24, 0x31, 0x01, 0xD7, 
206         0x02, 0x38, 0x11, 0xB6, 0x5E, 0x4A, 0xCC, 0x33, 0xF0, 0xEB, 0x0B, 0x38, 
207         0x51, 0x27, 0xCF, 0xAD, 0x20, 0x20, 0x9A, 0x80, 0x80, 0x37, 0xBE, 0x4C, 
208         0xBC, 0xA4, 0xC8, 0xE1, 0x5B, 0x57, 0x02, 0xC9, 0x04, 0x53, 0x82, 0x6E, 
209         0x0B, 0x06, 0x94, 0xCF, 0xC2, 0xEF, 0x1A, 0x6C, 0xC8, 0x78, 0x41, 0xB1, 
210         0x63, 0xBD, 0x52, 0x1C, 0x05, 0x2C, 0x97, 0x83, 0x10, 0xD0, 0xFE, 0x22, 
211         0x2F, 0x29, 0xAF, 0xC0, 0xCA, 0xC7, 0x96, 0x0A, 0x9A, 0xC8, 0x69, 0x58, 
212         0xBF, 0xA9, 0xDD, 0x75, 0xE4, 0xAB, 0xC8, 0xFE, 0xF5, 0xFE, 0xC5, 0x18, 
213         0x2B, 0x93, 0xC0, 0x67, 0xFF, 0xDC, 0xE3, 0xAF, 0xAC, 0x5F, 0x7E, 0x5F, 
214         0x0D, 0xEA, 0x41, 0xEB, 0x57, 0x1A, 0x4D, 0xB3, 0x10, 0x07, 0x09, 0xDC, 
215         0x3F, 0xC1, 0xB7, 0x9F, 0xC5, 0x79, 0xCD, 0x6E, 0x79, 0x48, 0x4F, 0x51, 
216         0xD8, 0x4B, 0x3A, 0x32, 0x40, 0x05, 0x6B, 0x74, 0xC9, 0xF4, 0xD9, 0x67, 
217         0x9D, 0x65, 0xFF, 0x4C, 0x4E, 0xAB, 0xC0, 0xC5, 0x65, 0x49, 0xEB, 0x6D, 
218         0xAB, 0xB9, 0x30, 0x5A, 0xFC, 0x5D, 0xD4, 0xE7, 0xB5, 0xDB, 0xD3, 0xF1, 
219         0xBF, 0x6F, 0xD4, 0x18, 0xD6, 0xE7, 0x76, 0x12, 0xCE, 0x57, 0xDF, 0x63, 
220         0x2C, 0x88, 0x2F, 0x0F, 0x31, 0x3A, 0x78, 0xA0, 0xB9, 0x5A, 0x11, 0x50, 
221         0x18, 0x98, 0xA4, 0xA3, 0x9D, 0xC7, 0xC4, 0x5C, 0xE7, 0xDF, 0xFD, 0x4B, 
222         0x96, 0x84, 0x27, 0x4C, 0x84, 0x92, 0xE9, 0x5E, 0x93, 0x65, 0x0C, 0xC9, 
223         0xB4, 0x5B, 0xE7, 0xC0, 0x26, 0x66, 0x36, 0x7A, 0x36, 0x56, 0xB0, 0xC8, 
224         0x34, 0xBB, 0x4F, 0xBD, 0x0E, 0xDA, 0x04, 0x82, 0x74, 0x07, 0x3D, 0xD3, 
225         0x1D, 0x8F, 0x9B, 0x34, 0x4F, 0xA8, 0xD5, 0x58, 0x12, 0xE8, 0x96, 0x20 };
226
227         [Test]
228         public void MSPasswordWeak () 
229         {
230                 WriteBuffer (pwd);
231                 PrivateKey pvk = PrivateKey.CreateFromFile (testfile, "password");
232                 AssertNotNull ("mspwd.RSA", pvk.RSA);
233                 Assert ("mspwd.Encrypted", pvk.Encrypted);
234                 Assert ("mspwd.Weak", pvk.Weak);
235         }
236
237         // this will convert a PVK file with a password to a PVK file
238         // without a password
239         [Test]
240         public void RemovePassword () 
241         {
242                 WriteBuffer (nopwd);
243                 PrivateKey pvk = PrivateKey.CreateFromFile (testfile, "password");
244                 string rsa1 = pvk.RSA.ToXmlString (true);
245                 pvk.Save (testfile);
246                 pvk = PrivateKey.CreateFromFile (testfile);
247                 AssertNotNull ("nomorepwd.RSA", pvk.RSA);
248                 string rsa2 = pvk.RSA.ToXmlString (true);
249                 AssertEquals ("nomorepwd.RSA identical", rsa1, rsa2);
250                 Assert ("nomorepwd.Encrypted", !pvk.Encrypted);
251                 Assert ("nomorepwd.Weak", pvk.Weak);
252         }
253         
254         [Test]
255         public void CreatePVK () 
256         {
257                 PrivateKey pvk = new PrivateKey ();
258                 pvk.KeyType = 2;
259                 pvk.RSA = RSA.Create ();
260                 string rsa1 = pvk.RSA.ToXmlString (true);
261                 pvk.Save (testfile, "mono");
262
263                 pvk = PrivateKey.CreateFromFile (testfile, "mono");
264                 AssertNotNull ("new.RSA", pvk.RSA);
265                 string rsa2 = pvk.RSA.ToXmlString (true);
266                 AssertEquals ("new.RSA identical", rsa1, rsa2);
267                 Assert ("new.Encrypted", pvk.Encrypted);
268                 Assert ("new.Weak", !pvk.Weak);
269         }
270
271         [Test]
272         [ExpectedException (typeof (ArgumentNullException))]
273         public void Save_Null () 
274         {
275                 PrivateKey pvk = new PrivateKey ();
276                 pvk.Save (null, "mono");
277         }
278         
279         [Test]
280         [ExpectedException (typeof (CryptographicException))]
281         public void BadMagic () 
282         {
283                 byte[] bad = (byte[]) nopwd.Clone ();
284                 bad [0] = 0x00;
285                 WriteBuffer (bad);
286                 PrivateKey pvk = PrivateKey.CreateFromFile (testfile, null);
287         }
288         
289         [Test]
290         [ExpectedException (typeof (CryptographicException))]
291         public void BadHeader () 
292         {
293                 byte[] bad = (byte[]) nopwd.Clone ();
294                 bad [4] = 0x01;
295                 WriteBuffer (bad);
296                 PrivateKey pvk = PrivateKey.CreateFromFile (testfile, null);
297         }
298
299         [Test]
300         [ExpectedException (typeof (CryptographicException))]
301         public void SaltWithoutPassword () 
302         {
303                 byte[] bad = (byte[]) nopwd.Clone ();
304                 int saltlen = BitConverterLE.ToInt32 (bad, 16);
305                 int keylen = BitConverterLE.ToInt32 (bad, 20);
306                 // preserve total length
307                 saltlen += 8;
308                 keylen -= 8;
309                 // modify blob
310                 byte[] data = BitConverterLE.GetBytes (saltlen);
311                 Buffer.BlockCopy (data, 0, bad, 16, data.Length); 
312                 data = BitConverterLE.GetBytes (keylen);
313                 Buffer.BlockCopy (data, 0, bad, 20, data.Length); 
314                 // save-n-load          
315                 WriteBuffer (bad);
316                 PrivateKey pvk = PrivateKey.CreateFromFile (testfile, null);
317         }
318         
319         [Test]
320         [ExpectedException (typeof (ArgumentNullException))]
321         public void CreateFromFile_Null () 
322         {
323                 PrivateKey pvk = PrivateKey.CreateFromFile (null, "password");
324         }
325
326         [Test]
327         [ExpectedException (typeof (ArgumentNullException))]
328         public void Constructor_Null () 
329         {
330                 PrivateKey pvk = new PrivateKey (null, "password");
331         }
332 }
333
334 }