2 // PrivateKeyTest.cs - NUnit Test Cases for Private Key File
5 // Sebastien Pouliot (sebastien@ximian.com)
8 // (C) 2003 Motus Technologies Inc. (http://www.motus.com)
9 // Copyright (C) 2004 Novell (http://www.novell.com)
14 using System.Security.Cryptography;
17 using Mono.Security.Authenticode;
18 using NUnit.Framework;
20 namespace MonoTests.Mono.Security.Authenticode {
22 // partial copy of /mcs/class/Mono.Security/Mono.Security/BitConverterLE.cs
23 internal sealed class BitConverterLE {
25 private BitConverterLE ()
29 unsafe private static byte[] GetUIntBytes (byte *bytes)
31 if (BitConverter.IsLittleEndian)
32 return new byte [] { bytes [0], bytes [1], bytes [2], bytes [3] };
34 return new byte [] { bytes [3], bytes [2], bytes [1], bytes [0] };
37 unsafe internal static byte[] GetBytes (int value)
39 return GetUIntBytes ((byte *) &value);
42 unsafe private static void UIntFromBytes (byte *dst, byte[] src, int startIndex)
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];
50 dst [0] = src [startIndex + 3];
51 dst [1] = src [startIndex + 2];
52 dst [2] = src [startIndex + 1];
53 dst [3] = src [startIndex];
57 unsafe internal static int ToInt32 (byte[] value, int startIndex)
61 UIntFromBytes ((byte *) &ret, value, startIndex);
67 // HOWTO create a PVK file (on Windows using MS tools)
68 // makecert -n "CN=PVK1" -sv 1.pvk 1.cer
71 public class PrivateKeyTest : Assertion {
73 // because most crypto stuff works with byte[] buffers
74 static public void AssertEquals (string msg, byte[] array1, byte[] array2)
76 if ((array1 == null) && (array2 == null))
79 Fail (msg + " -> First array is NULL");
81 Fail (msg + " -> Second array is NULL");
83 bool a = (array1.Length == array2.Length);
85 for (int i = 0; i < array1.Length; i++) {
86 if (array1 [i] != array2 [i]) {
92 if (array1.Length > 0) {
93 msg += " -> Expected " + BitConverter.ToString (array1, 0);
94 msg += " is different than " + BitConverter.ToString (array2, 0);
102 public void FixtureSetup ()
104 testfile = Path.Combine (Path.GetTempPath (), "test.pvk");
108 public void TearDown ()
110 File.Delete (testfile);
113 private void WriteBuffer (byte[] buffer)
115 FileStream fs = File.Create (testfile);
116 fs.Write (buffer, 0, buffer.Length);
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 };
151 public void MSNoPassword ()
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);
161 // this will convert a PVK file without a password to a PVK file
162 // with a password (weak)
164 public void ConvertToPasswordWeak ()
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);
178 // this will convert a PVK file without a password to a PVK file
179 // with a password (strong)
181 public void ConvertToPasswordStrong ()
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);
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 };
228 public void MSPasswordWeak ()
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);
237 // this will convert a PVK file with a password to a PVK file
238 // without a password
240 public void RemovePassword ()
243 PrivateKey pvk = PrivateKey.CreateFromFile (testfile, "password");
244 string rsa1 = pvk.RSA.ToXmlString (true);
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);
255 public void CreatePVK ()
257 PrivateKey pvk = new PrivateKey ();
259 pvk.RSA = RSA.Create ();
260 string rsa1 = pvk.RSA.ToXmlString (true);
261 pvk.Save (testfile, "mono");
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);
272 [ExpectedException (typeof (ArgumentNullException))]
273 public void Save_Null ()
275 PrivateKey pvk = new PrivateKey ();
276 pvk.Save (null, "mono");
280 [ExpectedException (typeof (CryptographicException))]
281 public void BadMagic ()
283 byte[] bad = (byte[]) nopwd.Clone ();
286 PrivateKey pvk = PrivateKey.CreateFromFile (testfile, null);
290 [ExpectedException (typeof (CryptographicException))]
291 public void BadHeader ()
293 byte[] bad = (byte[]) nopwd.Clone ();
296 PrivateKey pvk = PrivateKey.CreateFromFile (testfile, null);
300 [ExpectedException (typeof (CryptographicException))]
301 public void SaltWithoutPassword ()
303 byte[] bad = (byte[]) nopwd.Clone ();
304 int saltlen = BitConverterLE.ToInt32 (bad, 16);
305 int keylen = BitConverterLE.ToInt32 (bad, 20);
306 // preserve total length
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);
316 PrivateKey pvk = PrivateKey.CreateFromFile (testfile, null);
320 [ExpectedException (typeof (ArgumentNullException))]
321 public void CreateFromFile_Null ()
323 PrivateKey pvk = PrivateKey.CreateFromFile (null, "password");
327 [ExpectedException (typeof (ArgumentNullException))]
328 public void Constructor_Null ()
330 PrivateKey pvk = new PrivateKey (null, "password");