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);
99 private const string testfile = "test.pvk";
102 public void TearDown ()
104 File.Delete (testfile);
107 private void WriteBuffer (byte[] buffer)
109 FileStream fs = File.Create (testfile);
110 fs.Write (buffer, 0, buffer.Length);
114 static byte[] nopwd = {
115 0x1E, 0xF1, 0xB5, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
116 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x01, 0x00, 0x00,
117 0x07, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x52, 0x53, 0x41, 0x32,
118 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0xDB, 0x27, 0x34, 0xCB,
119 0x3D, 0x27, 0xA0, 0x4F, 0x50, 0x68, 0xC7, 0x95, 0x4B, 0x7B, 0x69, 0xD1,
120 0xFD, 0x30, 0x58, 0x72, 0x6B, 0xFF, 0x77, 0x64, 0x96, 0x35, 0x72, 0x36,
121 0x98, 0xCE, 0x56, 0xDD, 0x94, 0x43, 0x7C, 0x0D, 0x61, 0x5C, 0x3A, 0xD6,
122 0x1E, 0xD1, 0x89, 0x6C, 0xD5, 0x9B, 0x3E, 0xD3, 0x60, 0x3E, 0x28, 0x3F,
123 0xC6, 0x51, 0x35, 0x0D, 0x4F, 0x7E, 0x79, 0xE6, 0xAE, 0xE4, 0xC8, 0xE9,
124 0xA9, 0x14, 0x6E, 0xD2, 0xBD, 0x42, 0xB2, 0x14, 0x82, 0xEE, 0x26, 0x8F,
125 0x21, 0x33, 0x1A, 0xD5, 0xD7, 0x6D, 0x90, 0xED, 0xC1, 0xA4, 0x1C, 0x84,
126 0x3F, 0xA3, 0x8A, 0xFB, 0x33, 0x30, 0x32, 0xF6, 0xE3, 0xE6, 0xC8, 0x81,
127 0x54, 0x88, 0x1A, 0x92, 0xF0, 0xBA, 0xB8, 0x4F, 0x52, 0x8D, 0xBD, 0x04,
128 0x47, 0xBC, 0x55, 0xBC, 0xD0, 0x3D, 0x2C, 0x7F, 0x4F, 0xAB, 0x99, 0xDC,
129 0xFB, 0x2D, 0x18, 0xF3, 0x99, 0x77, 0x10, 0x82, 0x48, 0xF3, 0xDE, 0x36,
130 0xD7, 0x62, 0xA9, 0xCB, 0x58, 0x01, 0x97, 0x79, 0x66, 0x0D, 0x01, 0x1F,
131 0xCC, 0x0B, 0xAB, 0x02, 0xA9, 0xE3, 0xF5, 0x85, 0xA8, 0x52, 0xBC, 0x10,
132 0xD7, 0x90, 0x60, 0x60, 0x50, 0xB1, 0x08, 0x01, 0x85, 0x52, 0xAC, 0x05,
133 0xF1, 0xCE, 0xF9, 0xE7, 0xBE, 0xDE, 0x46, 0x64, 0x40, 0xE5, 0x07, 0x82,
134 0x20, 0xDD, 0x48, 0xF1, 0xE1, 0x85, 0x29, 0x8C, 0xFE, 0x57, 0x7C, 0x65,
135 0xF5, 0x5C, 0x51, 0x9F, 0x63, 0xDE, 0xFC, 0x9C, 0xF9, 0x3F, 0x3D, 0xF2,
136 0xDC, 0x9F, 0x65, 0x27, 0xEC, 0x50, 0x54, 0xB9, 0xCE, 0xF2, 0xC3, 0x10,
137 0x93, 0x8B, 0xBE, 0x6A, 0xC1, 0x35, 0x19, 0xBB, 0x66, 0xA5, 0x5E, 0xEA,
138 0x91, 0x1D, 0xFB, 0x26, 0xF8, 0x0F, 0x5C, 0x13, 0x73, 0xCC, 0x9A, 0x68,
139 0x4C, 0x08, 0x9C, 0x02, 0xE5, 0xD5, 0x91, 0x37, 0x13, 0x68, 0x3D, 0xFC,
140 0x3E, 0xA7, 0x43, 0x94, 0xBC, 0xFC, 0x4F, 0xB1, 0x8E, 0xC5, 0x5F, 0x24,
141 0x9A, 0x6C, 0xDB, 0xC2, 0x49, 0x91, 0xEC, 0x2B, 0xB9, 0x3D, 0x2B, 0x96,
142 0xA3, 0x60, 0xE3, 0xA8, 0x8C, 0x28, 0xB7, 0x53 };
145 public void MSNoPassword ()
148 PrivateKey pvk = PrivateKey.CreateFromFile (testfile);
149 AssertNotNull ("msnopwd.RSA", pvk.RSA);
150 Assert ("msnopwd.Encrypted", !pvk.Encrypted);
151 Assert ("msnopwd.Weak", pvk.Weak);
152 AssertEquals ("msnopwd.KeyType", 2, pvk.KeyType);
155 // this will convert a PVK file without a password to a PVK file
156 // with a password (weak)
158 public void ConvertToPasswordWeak ()
161 PrivateKey pvk = PrivateKey.CreateFromFile (testfile);
162 string rsa1 = pvk.RSA.ToXmlString (true);
163 pvk.Save (testfile, "password");
164 pvk = PrivateKey.CreateFromFile (testfile, "password");
165 AssertNotNull ("topwd.RSA", pvk.RSA);
166 string rsa2 = pvk.RSA.ToXmlString (true);
167 AssertEquals ("topwd.RSA identical", rsa1, rsa2);
168 Assert ("topwd.Encrypted", pvk.Encrypted);
169 Assert ("topwd.Weak", pvk.Weak);
172 // this will convert a PVK file without a password to a PVK file
173 // with a password (strong)
175 public void ConvertToPasswordStrong ()
178 PrivateKey pvk = PrivateKey.CreateFromFile (testfile);
179 string rsa1 = pvk.RSA.ToXmlString (true);
180 pvk.Weak = false; // we want strong crypto
181 pvk.Save (testfile, "password");
182 pvk = PrivateKey.CreateFromFile (testfile, "password");
183 AssertNotNull ("topwd.RSA", pvk.RSA);
184 string rsa2 = pvk.RSA.ToXmlString (true);
185 AssertEquals ("topwd.RSA identical", rsa1, rsa2);
186 Assert ("topwd.Encrypted", pvk.Encrypted);
187 Assert ("topwd.Weak", !pvk.Weak);
190 static byte[] pwd = {
191 0x1E, 0xF1, 0xB5, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
192 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x34, 0x01, 0x00, 0x00,
193 0x37, 0x53, 0x7C, 0x99, 0x01, 0xB5, 0x50, 0xF3, 0x79, 0x6E, 0xDE, 0xD5,
194 0x8A, 0x1B, 0xED, 0x05, 0x07, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00,
195 0x33, 0x98, 0xE8, 0x81, 0xA2, 0x9A, 0xEB, 0x36, 0xEF, 0x1B, 0x52, 0xFD,
196 0xC3, 0x9B, 0xB7, 0x32, 0x02, 0xC0, 0x9F, 0xE0, 0x6A, 0x50, 0x81, 0x61,
197 0x37, 0xBE, 0xEC, 0x1B, 0xC3, 0x34, 0x7B, 0x03, 0x0B, 0xC8, 0x31, 0x7B,
198 0x0D, 0xA6, 0x7A, 0x05, 0xEA, 0xD1, 0xCA, 0x9A, 0xF3, 0x71, 0x84, 0x77,
199 0x9E, 0x6F, 0xD1, 0xD0, 0xA0, 0x62, 0xFF, 0x3D, 0x24, 0x31, 0x01, 0xD7,
200 0x02, 0x38, 0x11, 0xB6, 0x5E, 0x4A, 0xCC, 0x33, 0xF0, 0xEB, 0x0B, 0x38,
201 0x51, 0x27, 0xCF, 0xAD, 0x20, 0x20, 0x9A, 0x80, 0x80, 0x37, 0xBE, 0x4C,
202 0xBC, 0xA4, 0xC8, 0xE1, 0x5B, 0x57, 0x02, 0xC9, 0x04, 0x53, 0x82, 0x6E,
203 0x0B, 0x06, 0x94, 0xCF, 0xC2, 0xEF, 0x1A, 0x6C, 0xC8, 0x78, 0x41, 0xB1,
204 0x63, 0xBD, 0x52, 0x1C, 0x05, 0x2C, 0x97, 0x83, 0x10, 0xD0, 0xFE, 0x22,
205 0x2F, 0x29, 0xAF, 0xC0, 0xCA, 0xC7, 0x96, 0x0A, 0x9A, 0xC8, 0x69, 0x58,
206 0xBF, 0xA9, 0xDD, 0x75, 0xE4, 0xAB, 0xC8, 0xFE, 0xF5, 0xFE, 0xC5, 0x18,
207 0x2B, 0x93, 0xC0, 0x67, 0xFF, 0xDC, 0xE3, 0xAF, 0xAC, 0x5F, 0x7E, 0x5F,
208 0x0D, 0xEA, 0x41, 0xEB, 0x57, 0x1A, 0x4D, 0xB3, 0x10, 0x07, 0x09, 0xDC,
209 0x3F, 0xC1, 0xB7, 0x9F, 0xC5, 0x79, 0xCD, 0x6E, 0x79, 0x48, 0x4F, 0x51,
210 0xD8, 0x4B, 0x3A, 0x32, 0x40, 0x05, 0x6B, 0x74, 0xC9, 0xF4, 0xD9, 0x67,
211 0x9D, 0x65, 0xFF, 0x4C, 0x4E, 0xAB, 0xC0, 0xC5, 0x65, 0x49, 0xEB, 0x6D,
212 0xAB, 0xB9, 0x30, 0x5A, 0xFC, 0x5D, 0xD4, 0xE7, 0xB5, 0xDB, 0xD3, 0xF1,
213 0xBF, 0x6F, 0xD4, 0x18, 0xD6, 0xE7, 0x76, 0x12, 0xCE, 0x57, 0xDF, 0x63,
214 0x2C, 0x88, 0x2F, 0x0F, 0x31, 0x3A, 0x78, 0xA0, 0xB9, 0x5A, 0x11, 0x50,
215 0x18, 0x98, 0xA4, 0xA3, 0x9D, 0xC7, 0xC4, 0x5C, 0xE7, 0xDF, 0xFD, 0x4B,
216 0x96, 0x84, 0x27, 0x4C, 0x84, 0x92, 0xE9, 0x5E, 0x93, 0x65, 0x0C, 0xC9,
217 0xB4, 0x5B, 0xE7, 0xC0, 0x26, 0x66, 0x36, 0x7A, 0x36, 0x56, 0xB0, 0xC8,
218 0x34, 0xBB, 0x4F, 0xBD, 0x0E, 0xDA, 0x04, 0x82, 0x74, 0x07, 0x3D, 0xD3,
219 0x1D, 0x8F, 0x9B, 0x34, 0x4F, 0xA8, 0xD5, 0x58, 0x12, 0xE8, 0x96, 0x20 };
222 public void MSPasswordWeak ()
225 PrivateKey pvk = PrivateKey.CreateFromFile (testfile, "password");
226 AssertNotNull ("mspwd.RSA", pvk.RSA);
227 Assert ("mspwd.Encrypted", pvk.Encrypted);
228 Assert ("mspwd.Weak", pvk.Weak);
231 // this will convert a PVK file with a password to a PVK file
232 // without a password
234 public void RemovePassword ()
237 PrivateKey pvk = PrivateKey.CreateFromFile (testfile, "password");
238 string rsa1 = pvk.RSA.ToXmlString (true);
240 pvk = PrivateKey.CreateFromFile (testfile);
241 AssertNotNull ("nomorepwd.RSA", pvk.RSA);
242 string rsa2 = pvk.RSA.ToXmlString (true);
243 AssertEquals ("nomorepwd.RSA identical", rsa1, rsa2);
244 Assert ("nomorepwd.Encrypted", !pvk.Encrypted);
245 Assert ("nomorepwd.Weak", pvk.Weak);
249 public void CreatePVK ()
251 PrivateKey pvk = new PrivateKey ();
253 pvk.RSA = RSA.Create ();
254 string rsa1 = pvk.RSA.ToXmlString (true);
255 pvk.Save (testfile, "mono");
257 pvk = PrivateKey.CreateFromFile (testfile, "mono");
258 AssertNotNull ("new.RSA", pvk.RSA);
259 string rsa2 = pvk.RSA.ToXmlString (true);
260 AssertEquals ("new.RSA identical", rsa1, rsa2);
261 Assert ("new.Encrypted", pvk.Encrypted);
262 Assert ("new.Weak", !pvk.Weak);
266 [ExpectedException (typeof (ArgumentNullException))]
267 public void Save_Null ()
269 PrivateKey pvk = new PrivateKey ();
270 pvk.Save (null, "mono");
274 [ExpectedException (typeof (CryptographicException))]
275 public void BadMagic ()
277 byte[] bad = (byte[]) nopwd.Clone ();
280 PrivateKey pvk = PrivateKey.CreateFromFile (testfile, null);
284 [ExpectedException (typeof (CryptographicException))]
285 public void BadHeader ()
287 byte[] bad = (byte[]) nopwd.Clone ();
290 PrivateKey pvk = PrivateKey.CreateFromFile (testfile, null);
294 [ExpectedException (typeof (CryptographicException))]
295 public void SaltWithoutPassword ()
297 byte[] bad = (byte[]) nopwd.Clone ();
298 int saltlen = BitConverterLE.ToInt32 (bad, 16);
299 int keylen = BitConverterLE.ToInt32 (bad, 20);
300 // preserve total length
304 byte[] data = BitConverterLE.GetBytes (saltlen);
305 Buffer.BlockCopy (data, 0, bad, 16, data.Length);
306 data = BitConverterLE.GetBytes (keylen);
307 Buffer.BlockCopy (data, 0, bad, 20, data.Length);
310 PrivateKey pvk = PrivateKey.CreateFromFile (testfile, null);
314 [ExpectedException (typeof (ArgumentNullException))]
315 public void CreateFromFile_Null ()
317 PrivateKey pvk = PrivateKey.CreateFromFile (null, "password");
321 [ExpectedException (typeof (ArgumentNullException))]
322 public void Constructor_Null ()
324 PrivateKey pvk = new PrivateKey (null, "password");