1 /**
  2  *  ---------
  3  * |.##> <##.|  Open Smart Card Development Platform (www.openscdp.org)
  4  * |#       #|
  5  * |#       #|  Copyright (c) 1999-2009 CardContact Software & System Consulting
  6  * |'##> <##'|  Andreas Schwier, 32429 Minden, Germany (www.cardcontact.de)
  7  *  ---------
  8  *
  9  *  This file is part of OpenSCDP.
 10  *
 11  *  OpenSCDP is free software; you can redistribute it and/or modify
 12  *  it under the terms of the GNU General Public License version 2 as
 13  *  published by the Free Software Foundation.
 14  *
 15  *  OpenSCDP is distributed in the hope that it will be useful,
 16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 18  *  GNU General Public License for more details.
 19  *
 20  *  You should have received a copy of the GNU General Public License
 21  *  along with OpenSCDP; if not, write to the Free Software
 22  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 23  *
 24  * @fileoverview Common classes and functions for PKIX
 25  */
 26 
 27 
 28 
 29 /**
 30  * Common functions and constants
 31  */
 32 function PKIXCommon() {
 33 }
 34 
 35 exports.PKIXCommon = PKIXCommon;
 36 
 37 
 38 PKIXCommon.digitalSignature	= 0x0080;
 39 PKIXCommon.nonRepudiation	= 0x0040;
 40 PKIXCommon.keyEncipherment	= 0x0020;
 41 PKIXCommon.dataEncipherment	= 0x0010;
 42 PKIXCommon.keyAgreement		= 0x0008;
 43 PKIXCommon.keyCertSign		= 0x0004;
 44 PKIXCommon.cRLSign		= 0x0002;
 45 PKIXCommon.encipherOnly		= 0x0001;
 46 PKIXCommon.decipherOnly		= 0x8000;
 47 
 48 
 49 
 50 /**
 51  * Convert integer to fixed length string with leading zeros.
 52  *
 53  * @private
 54  * @param {Number} value the value to convert to a string.
 55  * @param {Number} digits the number of digits in output string. Must be <= 20.
 56  * @return the 0-padded string
 57  * @type String
 58  */
 59 PKIXCommon.itos = function(value, digits) {
 60 	if (digits > 20) {
 61 		throw new Error("Digits must be <= 20");
 62 	}
 63 	var str = "" + value;
 64 	str = "0000000000000000000".substr(19 - (digits - str.length)).concat(str);
 65 	return str;
 66 }
 67 
 68 
 69 
 70 /**
 71  * Convert date and time to UTC string with format YYMMDDHHMMSSZ.
 72  *
 73  * @param {Date} d the date object.
 74  * @return the date/time string.
 75  * @type String
 76  */
 77 PKIXCommon.dtoUTC = function(d) {
 78 	var s = PKIXCommon.itos(d.getUTCFullYear() % 100, 2) +
 79 			PKIXCommon.itos(d.getUTCMonth() + 1, 2) +
 80 			PKIXCommon.itos(d.getUTCDate(), 2) +
 81 			PKIXCommon.itos(d.getUTCHours(), 2) +
 82 			PKIXCommon.itos(d.getUTCMinutes(), 2) +
 83 			PKIXCommon.itos(d.getUTCSeconds(), 2) + "Z";
 84 	return s;
 85 }
 86 
 87 
 88 
 89 /**
 90  * Convert date and time to UTC string with format YYYYMMDDHHMMSSZ.
 91  *
 92  * @param {Date} d the date object.
 93  * @return the date/time string.
 94  * @type String
 95  */
 96 PKIXCommon.dtoUTCFullYear = function(d) {
 97 	var s = 	d.getUTCFullYear() +
 98 			PKIXCommon.itos(d.getUTCMonth() + 1, 2) +
 99 			PKIXCommon.itos(d.getUTCDate(), 2) +
100 			PKIXCommon.itos(d.getUTCHours(), 2) +
101 			PKIXCommon.itos(d.getUTCMinutes(), 2) +
102 			PKIXCommon.itos(d.getUTCSeconds(), 2) + "Z";
103 	return s;
104 }
105 
106 
107 
108 /**
109  * Add the specified number of days to a date object
110  *
111  * @param {Date} d the date object
112  * @param {Number} days the number of days to add, may be negative
113  * @type Date
114  * @return a new Date object
115  */
116 PKIXCommon.addDays = function(d, days) {
117 	var hour = d.getUTCHours();
118 	var minute = d.getUTCMinutes();
119 	var second = d.getUTCSeconds();
120 	var cd = new Date(d);
121 	cd.setHours(12);
122 
123 	var ts = cd.getTime();
124 	ts += days * 24 * 60 * 60 * 1000;
125 	var nd = new Date(ts);
126 
127 	nd.setUTCHours(hour);
128 	nd.setUTCMinutes(minute);
129 	nd.setUTCSeconds(second);
130 	return nd;
131 }
132 
133 
134 
135 /**
136  * Converts the integer value into a BIT STRING value.
137  * <p>The function interprets the integer value as bitmap, where
138  * bit 0 is the most significant bit of the least significant byte.</p>
139  * <p>The function adds the minimum number of bytes to the final bit string
140  * and encodes the "number of unused bits at the beginning.</p>
141  *
142  * @param {Number} val the value to convert
143  * @return the bit string
144  * @type ByteString
145  */
146 PKIXCommon.bitstringForInteger = function(val) {
147 	var bb = new ByteBuffer();
148 	var b = 0;
149 
150 	// Encode starting with the least significant byte
151 	while (val > 0) {
152 		b = val & 0xFF;
153 		bb.append(b);
154 		val = val >> 8;
155 	}
156 
157 	// Determine number of unused bits
158 	var i = 0;
159 	while ((i < 8) && !(b & 1)) {
160 		i++;
161 		b >>= 1;
162 	}
163 
164 	bb.insert(0, i);
165 	return bb.toByteString();
166 }
167 
168 
169 
170 /**
171  * Removes leading zeros and prepends a single '00' to ByteStrings which have the most significant bit set.
172  *
173  * This prevent interpretation of the integer representation if converted into
174  * a signed ASN1 INTEGER.
175  *
176  * @param {ByteString} value the value to convert
177  * @return the converted value
178  * @type ByteString
179  */
180 PKIXCommon.convertUnsignedInteger = function(value) {
181 	assert(value.length > 0);
182 
183 	var i = 0;
184 	for (var i = 0; (i < value.length - 1) && (value.byteAt(i) == 0); i++);
185 
186 	if (value.byteAt(i) >= 0x80) {
187 		value = (new ByteString("00", HEX)).concat(value.bytes(i));
188 	} else {
189 		value = value.bytes(i);
190 	}
191 
192 	return value;
193 }
194 
195 
196 
197 /**
198  * Removes leading zero byte.
199  *
200  * @param {ByteString} value the value to process
201  * @return the processed ByteString without leading zero byte
202  * @type ByteString
203  */
204 PKIXCommon.removeLeadingZeroBytes = function(value) {
205 	if (value.length > 0 && value.byteAt(0) == 0x00) {
206 		value = value.bytes(1);
207 	}
208 
209 	return value;
210 }
211 
212 
213 
214 /**
215  * Encode PSS algorithm parameter
216  */
217 PKIXCommon.encodePSSAlgorithmParameter = function(hashAlgorithm, saltLength) {
218 	var param =  new ASN1("parameters", ASN1.SEQUENCE,
219 			new ASN1("hashAlgorithm", 0xA0,
220 				new ASN1("sha256Identifier", ASN1.SEQUENCE,
221 					new ASN1("algorithm", ASN1.OBJECT_IDENTIFIER, hashAlgorithm),
222 					new ASN1("parameter", ASN1.NULL, new ByteString("", HEX)))),
223 			new ASN1("maskGenAlgorithm", 0xA1,
224 				new ASN1("mgf1SHA256Identifier", ASN1.SEQUENCE,
225 					new ASN1("algorithm", ASN1.OBJECT_IDENTIFIER, new ByteString("pkcs-1 8", OID)), // id-mgf1
226 					new ASN1("parameters", ASN1.SEQUENCE,
227 						new ASN1("algorithm", ASN1.OBJECT_IDENTIFIER, hashAlgorithm),
228 						new ASN1("parameter", ASN1.NULL, new ByteString("", HEX))))),
229 			new ASN1("hashAlgorithm", 0xA2,
230 				new ASN1("saltLength", ASN1.INTEGER, ByteString.valueOf(saltLength)))
231 			);
232 
233 	return param;
234 }
235 
236 
237 
238 /**
239  * Gets the signature algorithm TLV object
240  *
241  * @return the signature algorithm object
242  * @type ASN1
243  */
244 PKIXCommon.encodeSignatureAlgorithm = function(signatureAlgorithm) {
245 	var t = new ASN1("signatureAlgorithm", ASN1.SEQUENCE);
246 
247 	if ((signatureAlgorithm == Crypto.RSA) || (signatureAlgorithm == Crypto.RSA_SHA1)) {
248 		t.add(new ASN1("algorithm", ASN1.OBJECT_IDENTIFIER, new ByteString("sha1WithRSAEncryption", OID)));
249 		t.add(new ASN1("parameters", ASN1.NULL, new ByteString("", HEX)));
250 	} else if (signatureAlgorithm == Crypto.RSA_SHA256) {
251 		t.add(new ASN1("algorithm", ASN1.OBJECT_IDENTIFIER, new ByteString("sha256WithRSAEncryption", OID)));
252 		t.add(new ASN1("parameters", ASN1.NULL, new ByteString("", HEX)));
253 	} else if (signatureAlgorithm == Crypto.RSA_SHA384) {
254 		t.add(new ASN1("algorithm", ASN1.OBJECT_IDENTIFIER, new ByteString("sha384WithRSAEncryption", OID)));
255 		t.add(new ASN1("parameters", ASN1.NULL, new ByteString("", HEX)));
256 	} else if (signatureAlgorithm == Crypto.RSA_SHA512) {
257 		t.add(new ASN1("algorithm", ASN1.OBJECT_IDENTIFIER, new ByteString("sha512WithRSAEncryption", OID)));
258 		t.add(new ASN1("parameters", ASN1.NULL, new ByteString("", HEX)));
259 	} else if (signatureAlgorithm == Crypto.RSA_PSS_SHA1) {
260 		t.add(new ASN1("algorithm", ASN1.OBJECT_IDENTIFIER, new ByteString("id-RSASSA-PSS", OID)));
261 		t.add(new ASN1("parameters", ASN1.NULL, new ByteString("", HEX)));
262 	} else if (signatureAlgorithm == Crypto.RSA_PSS_SHA256) {
263 		t.add(new ASN1("algorithm", ASN1.OBJECT_IDENTIFIER, new ByteString("id-RSASSA-PSS", OID)));
264 		t.add(PKIXCommon.encodePSSAlgorithmParameter(new ByteString("id-sha256", OID), 32));
265 	} else if (signatureAlgorithm == Crypto.RSA_PSS_SHA384) {
266 		t.add(new ASN1("algorithm", ASN1.OBJECT_IDENTIFIER, new ByteString("id-RSASSA-PSS", OID)));
267 		t.add(PKIXCommon.encodePSSAlgorithmParameter(new ByteString("id-sha384", OID), 48));
268 	} else if (signatureAlgorithm == Crypto.RSA_PSS_SHA512) {
269 		t.add(new ASN1("algorithm", ASN1.OBJECT_IDENTIFIER, new ByteString("id-RSASSA-PSS", OID)));
270 		t.add(PKIXCommon.encodePSSAlgorithmParameter(new ByteString("id-sha512", OID), 64));
271 	} else if (signatureAlgorithm == Crypto.ECDSA_SHA1) {
272 		t.add(new ASN1("algorithm", ASN1.OBJECT_IDENTIFIER, new ByteString("ecdsa-with-SHA1", OID)));
273 	} else if (signatureAlgorithm == Crypto.ECDSA_SHA224) {
274 		t.add(new ASN1("algorithm", ASN1.OBJECT_IDENTIFIER, new ByteString("ecdsa-with-SHA224", OID)));
275 	} else if (signatureAlgorithm == Crypto.ECDSA_SHA256) {
276 		t.add(new ASN1("algorithm", ASN1.OBJECT_IDENTIFIER, new ByteString("ecdsa-with-SHA256", OID)));
277 	} else if (signatureAlgorithm == Crypto.ECDSA_SHA384) {
278 		t.add(new ASN1("algorithm", ASN1.OBJECT_IDENTIFIER, new ByteString("ecdsa-with-SHA384", OID)));
279 	} else if (signatureAlgorithm == Crypto.ECDSA_SHA512) {
280 		t.add(new ASN1("algorithm", ASN1.OBJECT_IDENTIFIER, new ByteString("ecdsa-with-SHA512", OID)));
281 	} else {
282 		throw new GPError(module.id, GPError.INVALID_MECH, signatureAlgorithm, "Invalid algorithm");
283 	}
284 
285 	return t;
286 }
287 
288 
289 
290 PKIXCommon.algIdMap = {};
291 PKIXCommon.algIdMap[(new ByteString("sha1WithRSAEncryption", OID)).toString(HEX)] = Crypto.RSA_SHA1;
292 PKIXCommon.algIdMap[(new ByteString("sha256WithRSAEncryption", OID)).toString(HEX)] = Crypto.RSA_SHA256;
293 PKIXCommon.algIdMap[(new ByteString("sha384WithRSAEncryption", OID)).toString(HEX)] = Crypto.RSA_SHA384;
294 PKIXCommon.algIdMap[(new ByteString("sha512WithRSAEncryption", OID)).toString(HEX)] = Crypto.RSA_SHA512;
295 PKIXCommon.algIdMap[(new ByteString("id-RSASSA-PSS", OID)).toString(HEX)] = Crypto.RSA_PSS_SHA1;
296 PKIXCommon.algIdMap[(new ByteString("ecdsa-with-SHA1", OID)).toString(HEX)] = Crypto.ECDSA_SHA1;
297 PKIXCommon.algIdMap[(new ByteString("ecdsa-with-SHA224", OID)).toString(HEX)] = Crypto.ECDSA_SHA224;
298 PKIXCommon.algIdMap[(new ByteString("ecdsa-with-SHA256", OID)).toString(HEX)] = Crypto.ECDSA_SHA256;
299 PKIXCommon.algIdMap[(new ByteString("ecdsa-with-SHA384", OID)).toString(HEX)] = Crypto.ECDSA_SHA384;
300 PKIXCommon.algIdMap[(new ByteString("ecdsa-with-SHA512", OID)).toString(HEX)] = Crypto.ECDSA_SHA512;
301 
302 
303 
304 /**
305  * Return Crypto.x constant for given signatureAlgorithm
306  *
307  * @param {ByteString} signatureAlgorithm the algorithm
308  * @param {ByteString} param the parameter (optional)
309  * @type Number
310  * @return the Crypto.X constant
311  */
312 PKIXCommon.decodeSignatureAlgorithm = function(signatureAlgorithm, param) {
313 	if (signatureAlgorithm.equals(new ByteString("id-RSASSA-PSS", OID))) {
314 		if (typeof(param) == "undefined") {
315 			return Crypto.RSA_PSS_SHA1;
316 		}
317 
318 		var a = new ASN1(param);
319 		var hashAlgorithm = null;
320 
321 		for (var i = 0; i < a.elements; i++) {
322 			var o = a.get(i);
323 			if (o.tag == 0xA0) { // hashAlgorithm
324 				var oid = o.get(0).get(0).value;
325 				hashAlgorithm = this.decodeHashAlgorithm(oid);
326 			} else if (o.tag == 0xA1) { // MGF
327 				// Check MGF
328 				var m = o.get(0).get(0).value;
329 				if (!m.equals(new ByteString("pkcs-1 8", OID))) {
330 					throw new GPError(module.id, GPError.INVALID_MECH, 2, "Unsupported MGF");
331 				}
332 
333 				// Check hashAlgorithm
334 				var oid = o.get(0).get(1).get(0).value;
335 				var h = this.decodeHashAlgorithm(oid);
336 				if (hashAlgorithm == null) {
337 					hashAlgorithm = h;
338 				} else if (hashAlgorithm != h) {
339 					throw new GPError(module.id, GPError.INVALID_MECH, 2, "Signature hash algorithm and MGF hash algorithm must be the same");
340 				}
341 			} else if (o.tag == 0xA2) { // saltLength
342 				switch(hashAlgorithm) {
343 					case Crypto.SHA_224:
344 						var expectedSalt = 28;
345 						break;
346 					case Crypto.SHA_256:
347 						var expectedSalt = 32;
348 						break;
349 					case Crypto.SHA_384:
350 						var expectedSalt = 48;
351 						break;
352 					case Crypto.SHA_512:
353 						var expectedSalt = 64;
354 						break;
355 					case Crypto.SHA_1:
356 					default:
357 						var expectedSalt = 20;
358 				}
359 
360 				var salt = o.get(0).value.toUnsigned();
361 				if (salt != expectedSalt) {
362 					throw new GPError(module.id, GPError.INVALID_MECH, 2, "saltLength (" + salt + ") must match hash size (" + expectedSalt + ")");
363 				}
364 			} else if (o.tag == 0xA3) { // trailerField
365 				var trailerField = o.get(0).value.toUnsigned();
366 				if (trailerField != 1) {
367 					throw new GPError(module.id, GPError.INVALID_MECH, 2, "trailerField value must be 1");
368 				}
369 			}
370 		}
371 
372 		switch(hashAlgorithm) {
373 			case Crypto.SHA_224:
374 				return Crypto.RSA_PSS_SHA224;
375 			case Crypto.SHA_256:
376 				return Crypto.RSA_PSS_SHA256;
377 			case Crypto.SHA_384:
378 				return Crypto.RSA_PSS_SHA384;
379 			case Crypto.SHA_512:
380 				return Crypto.RSA_PSS_SHA512;
381 			case Crypto.SHA_1:
382 			default:
383 				return Crypto.RSA_PSS_SHA1;
384 		}
385 	}
386 
387 	var alg = PKIXCommon.algIdMap[signatureAlgorithm.toString(HEX)];
388 	return alg;
389 }
390 
391 
392 /**
393  * Return Crypto.SHA_x constant for given OID
394  *
395  * @param {ByteString} oid the hash OID
396  * @type Number
397  * @return the Crypto.SHA_x constant
398  */
399 PKIXCommon.decodeHashAlgorithm = function(oid) {
400 	//var oid = algorithmId.get(0).get(0).value.toString(HEX);
401 
402 	switch (oid.toString(HEX)) {
403 		case new ByteString("id-sha1", OID).toString(HEX):
404 			return Crypto.SHA_1;
405 		case new ByteString("id-sha224", OID).toString(HEX):
406 			return Crypto.SHA_224;
407 		case new ByteString("id-sha256", OID).toString(HEX):
408 			return Crypto.SHA_256;
409 		case new ByteString("id-sha384", OID).toString(HEX):
410 			return Crypto.SHA_384;
411 		case new ByteString("id-sha512", OID).toString(HEX):
412 			return Crypto.SHA_512;
413 		default:
414 			throw new GPError(module.id, GPError.INVALID_MECH, 1, "Invalid algorithm");
415 	}
416 }
417 
418 
419 
420 /**
421  * Return Crypto.RSA or Crypto.EC depending on signature algorithm
422  *
423  * @param {Number} alg signature algorithm (one of Crypto.X)
424  * @type Number
425  * @return either Crypto.RSA or Crypto.EC
426  */
427 PKIXCommon.keyTypeForAlgorithm = function(alg) {
428 	if     ((alg == Crypto.RSA) ||
429 		(alg == Crypto.RSA_SHA256) ||
430 		(alg == Crypto.RSA_SHA384) ||
431 		(alg == Crypto.RSA_SHA512) ||
432 		(alg == Crypto.RSA_PSS_SHA1) ||
433 		(alg == Crypto.RSA_PSS_SHA224) ||
434 		(alg == Crypto.RSA_PSS_SHA256) ||
435 		(alg == Crypto.RSA_PSS_SHA384) ||
436 		(alg == Crypto.RSA_PSS_SHA512)) {
437 		return Crypto.RSA;
438 	} else {
439 		return Crypto.EC;
440 	}
441 }
442 
443 
444 
445 /**
446  * Create tailored AlgorithmIdentifier that restricts usage of the public key.
447  *
448  * @param{String} restriction The restriction to apply.
449  * @type ASN1
450  * @return the tailored AlgorithmIdentifier;
451  */
452 PKIXCommon.restrictedPublicKeyAlgorithmIdentifier = function(restriction) {
453 	switch(restriction) {
454 		case "PSS-SHA1":
455 			var puboid = new ByteString("id-RSASSA-PSS", OID);
456 			var hash = new ByteString("id-sha1", OID);
457 			break;
458 		case "PSS-SHA224":
459 			var puboid = new ByteString("id-RSASSA-PSS", OID);
460 			var hash = new ByteString("id-sha224", OID);
461 			break;
462 		case "PSS-SHA256":
463 			var puboid = new ByteString("id-RSASSA-PSS", OID);
464 			var hash = new ByteString("id-sha256", OID);
465 			break;
466 		case "PSS-SHA384":
467 			var puboid = new ByteString("id-RSASSA-PSS", OID);
468 			var hash = new ByteString("id-sha384", OID);
469 			break;
470 		case "PSS-SHA512":
471 			var puboid = new ByteString("id-RSASSA-PSS", OID);
472 			var hash = new ByteString("id-sha512", OID);
473 			break;
474 		case "OEAP":
475 		default:
476 			throw new GPError(module.id, GPError.INVALID_DATA, 0, "Unknown public key restriction " + this.policy.restrictPublicKey);
477 	}
478 
479 	var info = PKIXCommon.encodePSSAlgorithmParameter(hash, 0);
480 	var algorithm = new ASN1("algorithm", ASN1.SEQUENCE,
481 		new ASN1("algorithm", ASN1.OBJECT_IDENTIFIER, puboid),
482 		info
483 	);
484 
485 	return algorithm;
486 }
487 
488 
489 
490 /**
491  * Encode EC Parameter for inclusion in the AlgorithmIdentifier structure.
492  *
493  * @param{Key} publicKey the public key.
494  * @type ASN1
495  * @return the encoded ECParameter.
496  */
497 PKIXCommon.encodeECParameter = function(publicKey) {
498 	if (!publicKey.getComponent(Key.ECC_P)) {		// Make sure curve components are available if only curve oid is defined
499 		publicKey.setComponent(Key.ECC_CURVE_OID, publicKey.getComponent(Key.ECC_CURVE_OID));
500 	}
501 	var ecParameter =
502 		new ASN1("ecParameters", ASN1.SEQUENCE,
503 			new ASN1("version", ASN1.INTEGER, new ByteString("01", HEX)),
504 			new ASN1("fieldID", ASN1.SEQUENCE,
505 				new ASN1("fieldType", ASN1.OBJECT_IDENTIFIER, new ByteString("prime-field", OID)),
506 				new ASN1("prime", ASN1.INTEGER,
507 					PKIXCommon.convertUnsignedInteger(publicKey.getComponent(Key.ECC_P)))
508 			),
509 			new ASN1("curve", ASN1.SEQUENCE,
510 				new ASN1("a", ASN1.OCTET_STRING, publicKey.getComponent(Key.ECC_A)),
511 				new ASN1("b", ASN1.OCTET_STRING, publicKey.getComponent(Key.ECC_B))
512 			),
513 			new ASN1("base", ASN1.OCTET_STRING,
514 					(new ByteString("04", HEX)).concat(publicKey.getComponent(Key.ECC_GX)).concat(publicKey.getComponent(Key.ECC_GY))),
515 			new ASN1("order", ASN1.INTEGER,
516 				PKIXCommon.convertUnsignedInteger(publicKey.getComponent(Key.ECC_N)))
517 		);
518 
519 	var cofactor = publicKey.getComponent(Key.ECC_H);
520 	var i = 0;
521 	for (; (i < cofactor.length) && (cofactor.byteAt(i) == 0); i++);
522 	if (i < cofactor.length) {
523 		ecParameter.add(new ASN1("cofactor", ASN1.INTEGER, cofactor.bytes(i)));
524 	}
525 	return ecParameter;
526 }
527 
528 
529 
530 /**
531  * Creates the EC Public Key as subjectPublicKeyInfo TLV structure object.
532  *
533  * <p>The structure is defined as:</p>
534  * <pre>
535  *	SubjectPublicKeyInfo  ::=  SEQUENCE  {
536  *		algorithm            AlgorithmIdentifier,
537  *		subjectPublicKey     BIT STRING  }
538  *
539  *	AlgorithmIdentifier  ::=  SEQUENCE  {
540  *		algorithm               OBJECT IDENTIFIER,
541  *		parameters              ANY DEFINED BY algorithm OPTIONAL  }
542  *
543  *	id-ecPublicKey OBJECT IDENTIFIER ::= {
544  *		iso(1) member-body(2) us(840) ansi-X9-62(10045) keyType(2) 1 }
545  *
546  *	ECParameters ::= CHOICE {
547  *		namedCurve         OBJECT IDENTIFIER,
548  *		implicitCurve      NULL,
549  *		specifiedCurve     SpecifiedECDomain }
550  * </pre>
551  * @return the subjectPublicKey TLV structure
552  * @type ASN1
553  */
554 PKIXCommon.createECSubjectPublicKeyInfo = function(publicKey, encodeECDomainParameter) {
555 	var t = new ASN1("subjectPublicKeyInfo", ASN1.SEQUENCE);
556 
557 	var algorithm = publicKey.algorithmIdentifier;
558 	if (typeof(algorithm) == "undefined") {
559 		algorithm = new ASN1("algorithm", ASN1.SEQUENCE,
560 				new ASN1("algorithm", ASN1.OBJECT_IDENTIFIER, new ByteString("id-ecPublicKey", OID))
561 
562 			);
563 		if (encodeECDomainParameter) {
564 			algorithm.add(PKIXCommon.encodeECParameter(publicKey));
565 		} else {
566 			algorithm.add(new ASN1("parameters", ASN1.OBJECT_IDENTIFIER, publicKey.getComponent(Key.ECC_CURVE_OID)));
567 		}
568 	}
569 
570 	t.add(algorithm);
571 
572 	// Prefix a 00 to form correct bitstring
573 	// Prefix a 04 to indicate uncompressed format
574 	var keybin = new ByteString("0004", HEX);
575 	keybin = keybin.concat(publicKey.getComponent(Key.ECC_QX));
576 	keybin = keybin.concat(publicKey.getComponent(Key.ECC_QY));
577 	t.add(new ASN1("subjectPublicKey", ASN1.BIT_STRING, keybin));
578 
579 	return t;
580 }
581 
582 
583 
584 /**
585  * Creates the RSA Public Key as subjectPublicKeyInfo TLV structure object.
586  *
587  * <p>The structure is defined as:</p>
588  * <pre>
589  *	SubjectPublicKeyInfo  ::=  SEQUENCE  {
590  *		algorithm            AlgorithmIdentifier,
591  *		subjectPublicKey     BIT STRING  }
592  *
593  *	AlgorithmIdentifier  ::=  SEQUENCE  {
594  *		algorithm               OBJECT IDENTIFIER,
595  *		parameters              ANY DEFINED BY algorithm OPTIONAL  }
596  *
597  *	pkcs-1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 }
598  *
599  *	rsaEncryption OBJECT IDENTIFIER ::=  { pkcs-1 1}
600  *
601  *	RSAPublicKey ::= SEQUENCE {
602  *		modulus            INTEGER,    -- n
603  *		publicExponent     INTEGER  }  -- e
604  * </pre>
605  *
606  * @return the subjectPublicKey TLV structure
607  * @type ASN1
608  */
609 PKIXCommon.createRSASubjectPublicKeyInfo = function(publicKey) {
610 	var t = new ASN1("subjectPublicKeyInfo", ASN1.SEQUENCE);
611 
612 	var algorithm = publicKey.algorithmIdentifier;
613 	if (typeof(algorithm) == "undefined") {
614 		algorithm = new ASN1("algorithm", ASN1.SEQUENCE,
615 				new ASN1("algorithm", ASN1.OBJECT_IDENTIFIER, new ByteString("rsaEncryption", OID)),
616 				new ASN1("parameters", ASN1.NULL, new ByteString("", HEX))
617 			);
618 	}
619 
620 	t.add(algorithm);
621 	// Prefix a 00 to form correct bitstring
622 	var keybin = new ByteString("00", HEX);
623 
624 	var modulus = publicKey.getComponent(Key.MODULUS);
625 	modulus = PKIXCommon.convertUnsignedInteger(modulus);
626 
627 	var exponent = publicKey.getComponent(Key.EXPONENT);
628 	exponent = PKIXCommon.convertUnsignedInteger(exponent);
629 
630 	var rsapub = new ASN1("RSAPublicKey", ASN1.SEQUENCE,
631 			new ASN1("modulus", ASN1.INTEGER, modulus),
632 			new ASN1("publicKeyExponent", ASN1.INTEGER, exponent));
633 
634 	keybin = keybin.concat(rsapub.getBytes());
635 	t.add(new ASN1("subjectPublicKey", ASN1.BIT_STRING, keybin));
636 
637 	return t;
638 }
639 
640 
641 
642 /**
643  * Determine key identifier according to RFC5280 using SHA-1 over the SubjectPublicKeyInfo
644  *
645  * @param {Key} publicKey the public key
646  * @param {Boolean} encodeECDomainParameter true to include domain parameter in SPKI of EC key
647  */
648 PKIXCommon.determineKeyIdentifier = function(publicKey, encodeECDomainParameter) {
649 	if (typeof(encodeECDomainParameter) == "undefined") {
650 		encodeECDomainParameter = true;
651 	}
652 
653 	var spki;
654 
655 	if (publicKey.getComponent(Key.MODULUS)) {
656 		spki = PKIXCommon.createRSASubjectPublicKeyInfo(publicKey);
657 	} else {
658 		spki = PKIXCommon.createECSubjectPublicKeyInfo(publicKey, encodeECDomainParameter);
659 	}
660 
661 	var keyvalue = spki.get(1).value.bytes(1);
662 	var crypto = new Crypto();
663 	return (crypto.digest(Crypto.SHA_1, keyvalue));
664 }
665 
666 
667 
668 /**
669  * Creates a relative distinguished name component.
670  *
671  * <p>The structure is defined as:</p>
672  * <pre>
673  *	RelativeDistinguishedName ::=
674  *		SET SIZE (1..MAX) OF AttributeTypeAndValue
675  *
676  *	AttributeTypeAndValue ::= SEQUENCE {
677  *		type     AttributeType,
678  *		value    AttributeValue }
679  *
680  *	AttributeType ::= OBJECT IDENTIFIER
681  *
682  *	AttributeValue ::= ANY -- DEFINED BY AttributeType
683  *
684  *	DirectoryString ::= CHOICE {
685  *		teletexString           TeletexString (SIZE (1..MAX)),
686  *		printableString         PrintableString (SIZE (1..MAX)),
687  *		universalString         UniversalString (SIZE (1..MAX)),
688  *		utf8String              UTF8String (SIZE (1..MAX)),
689  *		bmpString               BMPString (SIZE (1..MAX)) }
690  *</pre>
691  *
692  * @param {String} name the components name
693  * @param {String} oid the oid for the RDN
694  * @param {ASN1} value the value object
695  * @return the
696  */
697 PKIXCommon.makeRDN = function(name, oid, value) {
698 	return new ASN1(name, ASN1.SET,
699 				new ASN1(ASN1.SEQUENCE,
700 					new ASN1(ASN1.OBJECT_IDENTIFIER, new ByteString(oid, OID)),
701 					value
702 				)
703 			);
704 }
705 
706 
707 
708 /**
709  * Adds names from the name object to the RDNSequence.
710  *
711  * @param {ASN1} t the sequence object
712  * @param {Object} name the name object
713  */
714 PKIXCommon.addNames = function(t, name) {
715 	if (name.C) {
716 		t.add(PKIXCommon.makeRDN("country", "id-at-countryName", new ASN1(ASN1.PrintableString, new ByteString(name.C, ASCII))));
717 	}
718 	if (name.ST) {
719 		t.add(PKIXCommon.makeRDN("stateOrProvinceName", "id-at-stateOrProvinceName", new ASN1(ASN1.UTF8String, new ByteString(name.ST, UTF8))));
720 	}
721 	if (name.O) {
722 		t.add(PKIXCommon.makeRDN("organization", "id-at-organizationName", new ASN1(ASN1.UTF8String, new ByteString(name.O, UTF8))));
723 	}
724 	if (name.OU) {
725 		t.add(PKIXCommon.makeRDN("organizationalUnit", "id-at-organizationalUnitName", new ASN1(ASN1.UTF8String, new ByteString(name.OU, UTF8))));
726 	}
727 	if (name.S) {
728 		t.add(PKIXCommon.makeRDN("stateOrProvince", "id-at-stateOrProvinceName", new ASN1(ASN1.UTF8String, new ByteString(name.S, UTF8))));
729 	}
730 	if (name.L) {
731 		t.add(PKIXCommon.makeRDN("locality", "id-at-localityName", new ASN1(ASN1.UTF8String, new ByteString(name.L, UTF8))));
732 	}
733 	if (name.DC) {
734 		t.add(PKIXCommon.makeRDN("domainComponent", "id-domainComponent", new ASN1(ASN1.UTF8String, new ByteString(name.DC, UTF8))));
735 	}
736 	if (name.T) {
737 		t.add(PKIXCommon.makeRDN("title", "id-at-title", new ASN1(ASN1.UTF8String, new ByteString(name.T, UTF8))));
738 	}
739 	if (name.G) {
740 		t.add(PKIXCommon.makeRDN("givenName", "id-at-givenName", new ASN1(ASN1.UTF8String, new ByteString(name.G, UTF8))));
741 	}
742 	if (name.SN) {
743 		t.add(PKIXCommon.makeRDN("surname", "id-at-surname", new ASN1(ASN1.UTF8String, new ByteString(name.SN, UTF8))));
744 	}
745 	if (name.CN) {
746 		t.add(PKIXCommon.makeRDN("commonName", "id-at-commonName", new ASN1(ASN1.UTF8String, new ByteString(name.CN, UTF8))));
747 	}
748 	if (name.SERIALNUMBER) {
749 		t.add(PKIXCommon.makeRDN("serialNumber", "id-at-serialNumber", new ASN1(ASN1.UTF8String, new ByteString(name.SERIALNUMBER, UTF8))));
750 	}
751 	if (name.DNQ) {
752 		t.add(PKIXCommon.makeRDN("dnQualifier", "id-at-dnQualifier", new ASN1(ASN1.UTF8String, new ByteString(name.DNQ, UTF8))));
753 	}
754 	if (name.E) {
755 		t.add(PKIXCommon.makeRDN("emailAddress", "id-emailAddress", new ASN1(ASN1.IA5String, new ByteString(name.E, ASCII))));
756 	}
757 	if (name.UID) {
758 		t.add(PKIXCommon.makeRDN("userId", "id-userId", new ASN1(ASN1.UTF8String, new ByteString(name.UID, UTF8))));
759 	}
760 }
761 
762 
763 
764 PKIXCommon.validRDN = [ "C","ST","L","O","OU","S","DC","T","G","SN","PSEUDONYM","CN","SERIALNUMBER","DNQ","E","UID" ];
765 
766 /**
767  * Gets the dn as TLV object
768  *
769  * <p>This function support two format for names</p>
770  * <pre>
771  *  var issuer = { C:"UT", O:"ACME Corporation", CN:"Test-CA" };
772  * or
773  *  var issuer = [ { C:"UT"}, { O:"ACME Corporation" }, { CN:"Test-CA"} ];
774  * </pre>
775  *
776  * <p>It supports the following RDNs:</p>
777  * <ul>
778  * <li>C - country</li>
779  * <li>ST - state</li>
780  * <li>O - organization</li>
781  * <li>OU - organizational unit</li>
782  * <li>S - state or province</li>
783  * <li>L - locality</li>
784  * <li>DC - domain component</li>
785  * <li>T - title</li>
786  * <li>G - given name</li>
787  * <li>SN - surname</li>
788  * <li>CN - common name</li>
789  * <li>SERIALNUMBER - serial number</li>
790  * <li>DNQ - domain name qualifier</li>
791  * <li>E - e-mail address</li>
792  * <li>UID - user Id</li>
793  * <p>The first format sorts the RDS in the sequence C,ST,L,O,OU,S,DC,T,G,SN,PSEUDONYM,CN,SERIALNUMBER,DNQ,E,UID</p>
794  * </ul>
795  * @param {Object} name the name object
796  * @return the RDNSequence
797  * @type ASN1
798  */
799 PKIXCommon.encodeName = function(name) {
800 	var t = new ASN1("subject", ASN1.SEQUENCE);
801 	if (typeof(name.C) == "undefined") {
802 		for (var i = 0; i < name.length; i++) {
803 			PKIXCommon.addNames(t, name[i]);
804 		}
805 	} else {
806 		PKIXCommon.addNames(t, name);
807 	}
808 	return t;
809 }
810 
811 
812 
813 /**
814  * Return the value of the last RDN
815  *
816  * @param {Object[]} dn the dn array
817  * @type String
818  * @return the value of the last RDN
819  */
820 PKIXCommon.makeName = function(rdnlist) {
821 	if (rdnlist.length == 0) {
822 		return undefined;
823 	}
824 	var l = rdnlist[rdnlist.length - 1];
825 
826 	for (var i in l) {
827 		return l[i];
828 	}
829 
830 	return undefined;
831 }
832 
833 
834 
835 PKIXCommon.parseDN = function(dn) {
836 	assert(typeof(dn) == "string", "Parameter dn must be string");
837 
838 	var e = dn.split(",");
839 	var rdnlist = [];
840 
841 	for (var i = 0; i < e.length; i++) {
842 		var p = e[i].split("=");
843 
844 		if (p.length < 2) {
845 			throw new GPError(module.id, GPError.INVALID_DATA, i, "Missing '=' in RDN " + e[i]);
846 		}
847 
848 		if (p.length > 2) {
849 			throw new GPError(module.id, GPError.INVALID_DATA, i, "Too many '=' in RDN " + e[i]);
850 		}
851 
852 		var key = p[0].trim().toUpperCase();
853 
854 		if (key.length == 0) {
855 			throw new GPError(module.id, GPError.INVALID_DATA, i, "Key in RDN " + e[i] + " can't be empty");
856 		}
857 
858 		if (PKIXCommon.validRDN.indexOf(key) == -1) {
859 			throw new GPError(module.id, GPError.INVALID_DATA, i, key + " is not a supported RDN (Valid RDNs are " + PKIXCommon.validRDN + ")");
860 		}
861 
862 		var value = p[1].trim();
863 
864 		if (value.length == 0) {
865 			throw new GPError(module.id, GPError.INVALID_DATA, i, "Value for " + key + " can't be empty");
866 		}
867 		var rdn = { };
868 		rdn[key] = value;
869 		rdnlist.push(rdn);
870 	}
871 	return rdnlist;
872 }
873 
874 
875 
876 /**
877  * Convert a DN parsed with parseDN() back into the string format
878  *
879  * @param {Object[]} dn the dn array
880  * @type String
881  * @return the DN in string format
882  */
883 PKIXCommon.dnToString = function(dn) {
884 	var str = "";
885 
886 	for (var i = 0; i < dn.length; i++) {
887 		if (str.length > 0) {
888 			str += ",";
889 		}
890 
891 		for (var j in dn[i]) {
892 			str += j + "=" + dn[i][j];
893 		}
894 	}
895 	return str;
896 }
897 
898 
899 
900 PKIXCommon.findRDN = function(rdnlist, c) {
901 	for (var i = 0; i < rdnlist.length; i++) {
902 		var v = rdnlist[i][c];
903 		if (v) {
904 			return v;
905 		}
906 	}
907 }
908 
909 
910 
911 PKIXCommon.countryNames = {
912 AF:"Afghanistan",
913 AX:"Aeland Islands",
914 AL:"Albania",
915 DZ:"Algeria",
916 AS:"American Samoa",
917 AD:"Andorra",
918 AO:"Angola",
919 AI:"Anguilla",
920 AQ:"Antarctica",
921 AG:"Antigua and Barbuda",
922 AR:"Argentina",
923 AM:"Armenia",
924 AW:"Aruba",
925 AU:"Australia",
926 AT:"Austria",
927 AZ:"Azerbaijan",
928 BS:"Bahamas",
929 BH:"Bahrain",
930 BD:"Bangladesh",
931 BB:"Barbados",
932 BY:"Belarus",
933 BE:"Belgium",
934 BZ:"Belize",
935 BJ:"Benin",
936 BM:"Bermuda",
937 BT:"Bhutan",
938 BO:"Bolivia, Plurinational State of",
939 BQ:"Bonaire, Sint Eustatius and Saba",
940 BA:"Bosnia and Herzegovina",
941 BW:"Botswana",
942 BV:"Bouvet Island",
943 BR:"Brazil",
944 IO:"British Indian Ocean Territory",
945 BN:"Brunei Darussalam",
946 BG:"Bulgaria",
947 BF:"Burkina Faso",
948 BI:"Burundi",
949 KH:"Cambodia",
950 CM:"Cameroon",
951 CA:"Canada",
952 CV:"Cape Verde",
953 KY:"Cayman Islands",
954 CF:"Central African Republic",
955 TD:"Chad",
956 CL:"Chile",
957 CN:"China",
958 CX:"Christmas Island",
959 CC:"Cocos (Keeling) Islands",
960 CO:"Colombia",
961 KM:"Comoros",
962 CG:"Congo",
963 CD:"Congo, the Democratic Republic of the",
964 CK:"Cook Islands",
965 CR:"Costa Rica",
966 CI:"Cote d'Ivoire",
967 HR:"Croatia",
968 CU:"Cuba",
969 CW:"Curacao",
970 CY:"Cyprus",
971 CZ:"Czech Republic",
972 DK:"Denmark",
973 DJ:"Djibouti",
974 DM:"Dominica",
975 DO:"Dominican Republic",
976 EC:"Ecuador",
977 EG:"Egypt",
978 SV:"El Salvador",
979 GQ:"Equatorial Guinea",
980 ER:"Eritrea",
981 EE:"Estonia",
982 ET:"Ethiopia",
983 FK:"Falkland Islands (Malvinas)",
984 FO:"Faroe Islands",
985 FJ:"Fiji",
986 FI:"Finland",
987 FR:"France",
988 GF:"French Guiana",
989 PF:"French Polynesia",
990 TF:"French Southern Territories",
991 GA:"Gabon",
992 GM:"Gambia",
993 GE:"Georgia",
994 DE:"Germany",
995 GH:"Ghana",
996 GI:"Gibraltar",
997 GR:"Greece",
998 GL:"Greenland",
999 GD:"Grenada",
1000 GP:"Guadeloupe",
1001 GU:"Guam",
1002 GT:"Guatemala",
1003 GG:"Guernsey",
1004 GN:"Guinea",
1005 GW:"Guinea-Bissau",
1006 GY:"Guyana",
1007 HT:"Haiti",
1008 HM:"Heard Island and McDonald Islands",
1009 VA:"Holy See (Vatican City State)",
1010 HN:"Honduras",
1011 HK:"Hong Kong",
1012 HU:"Hungary",
1013 IS:"Iceland",
1014 IN:"India",
1015 ID:"Indonesia",
1016 IR:"Iran, Islamic Republic of",
1017 IQ:"Iraq",
1018 IE:"Ireland",
1019 IM:"Isle of Man",
1020 IL:"Israel",
1021 IT:"Italy",
1022 JM:"Jamaica",
1023 JP:"Japan",
1024 JE:"Jersey",
1025 JO:"Jordan",
1026 KZ:"Kazakhstan",
1027 KE:"Kenya",
1028 KI:"Kiribati",
1029 KP:"Korea, Democratic People's Republic of",
1030 KR:"Korea, Republic of",
1031 KW:"Kuwait",
1032 KG:"Kyrgyzstan",
1033 LA:"Lao People's Democratic Republic",
1034 LV:"Latvia",
1035 LB:"Lebanon",
1036 LS:"Lesotho",
1037 LR:"Liberia",
1038 LY:"Libya",
1039 LI:"Liechtenstein",
1040 LT:"Lithuania",
1041 LU:"Luxembourg",
1042 MO:"Macao",
1043 MK:"Macedonia, the Former Yugoslav Republic of",
1044 MG:"Madagascar",
1045 MW:"Malawi",
1046 MY:"Malaysia",
1047 MV:"Maldives",
1048 ML:"Mali",
1049 MT:"Malta",
1050 MH:"Marshall Islands",
1051 MQ:"Martinique",
1052 MR:"Mauritania",
1053 MU:"Mauritius",
1054 YT:"Mayotte",
1055 MX:"Mexico",
1056 FM:"Micronesia, Federated States of",
1057 MD:"Moldova, Republic of",
1058 MC:"Monaco",
1059 MN:"Mongolia",
1060 ME:"Montenegro",
1061 MS:"Montserrat",
1062 MA:"Morocco",
1063 MZ:"Mozambique",
1064 MM:"Myanmar",
1065 NA:"Namibia",
1066 NR:"Nauru",
1067 NP:"Nepal",
1068 NL:"Netherlands",
1069 NC:"New Caledonia",
1070 NZ:"New Zealand",
1071 NI:"Nicaragua",
1072 NE:"Niger",
1073 NG:"Nigeria",
1074 NU:"Niue",
1075 NF:"Norfolk Island",
1076 MP:"Northern Mariana Islands",
1077 NO:"Norway",
1078 OM:"Oman",
1079 PK:"Pakistan",
1080 PW:"Palau",
1081 PS:"Palestine, State of",
1082 PA:"Panama",
1083 PG:"Papua New Guinea",
1084 PY:"Paraguay",
1085 PE:"Peru",
1086 PH:"Philippines",
1087 PN:"Pitcairn",
1088 PL:"Poland",
1089 PT:"Portugal",
1090 PR:"Puerto Rico",
1091 QA:"Qatar",
1092 RE:"Reunion",
1093 RO:"Romania",
1094 RU:"Russian Federation",
1095 RW:"Rwanda",
1096 BL:"Saint Bartholemy",
1097 SH:"Saint Helena, Ascension and Tristan da Cunha",
1098 KN:"Saint Kitts and Nevis",
1099 LC:"Saint Lucia",
1100 MF:"Saint Martin (French part)",
1101 PM:"Saint Pierre and Miquelon",
1102 VC:"Saint Vincent and the Grenadines",
1103 WS:"Samoa",
1104 SM:"San Marino",
1105 ST:"Sao Tome and Principe",
1106 SA:"Saudi Arabia",
1107 SN:"Senegal",
1108 RS:"Serbia",
1109 SC:"Seychelles",
1110 SL:"Sierra Leone",
1111 SG:"Singapore",
1112 SX:"Sint Maarten (Dutch part)",
1113 SK:"Slovakia",
1114 SI:"Slovenia",
1115 SB:"Solomon Islands",
1116 SO:"Somalia",
1117 ZA:"South Africa",
1118 GS:"South Georgia and the South Sandwich Islands",
1119 SS:"South Sudan",
1120 ES:"Spain",
1121 LK:"Sri Lanka",
1122 SD:"Sudan",
1123 SR:"Suriname",
1124 SJ:"Svalbard and Jan Mayen",
1125 SZ:"Swaziland",
1126 SE:"Sweden",
1127 CH:"Switzerland",
1128 SY:"Syrian Arab Republic",
1129 TW:"Taiwan, Province of China",
1130 TJ:"Tajikistan",
1131 TZ:"Tanzania, United Republic of",
1132 TH:"Thailand",
1133 TL:"Timor-Leste",
1134 TG:"Togo",
1135 TK:"Tokelau",
1136 TO:"Tonga",
1137 TT:"Trinidad and Tobago",
1138 TN:"Tunisia",
1139 TR:"Turkey",
1140 TM:"Turkmenistan",
1141 TC:"Turks and Caicos Islands",
1142 TV:"Tuvalu",
1143 UG:"Uganda",
1144 UA:"Ukraine",
1145 AE:"United Arab Emirates",
1146 GB:"United Kingdom",
1147 US:"United States",
1148 UM:"United States Minor Outlying Islands",
1149 UY:"Uruguay",
1150 UZ:"Uzbekistan",
1151 VU:"Vanuatu",
1152 VE:"Venezuela, Bolivarian Republic of",
1153 VN:"Viet Nam",
1154 VG:"Virgin Islands, British",
1155 VI:"Virgin Islands, U.S.",
1156 WF:"Wallis and Futuna",
1157 EH:"Western Sahara",
1158 YE:"Yemen",
1159 ZM:"Zambia",
1160 ZW:"Zimbabwe"
1161 };
1162 
1163 
1164 
1165 /**
1166  * Extract subject from certificate as ASN1 object
1167  *
1168  * @param {X509} cert the certificate
1169  * @type ASN1
1170  * @return the subject as ASN1
1171  */
1172 PKIXCommon.getSubjectAsASN1 = function(cert) {
1173 	var a = new ASN1(cert.getBytes());
1174 	return a.get(0).get(5);
1175 }
1176 
1177 
1178 
1179 /**
1180  * Extract issuer from certificate as ASN1 object
1181  *
1182  * @param {X509} cert the certificate
1183  * @type ASN1
1184  * @return the issuer as ASN1
1185  */
1186 PKIXCommon.getIssuerAsASN1 = function(cert) {
1187 	var a = new ASN1(cert.getBytes());
1188 	return a.get(0).get(3);
1189 }
1190 
1191 
1192 
1193 /**
1194  * Convert binary data to PEM format
1195  *
1196  * @param {String} label the label to be used in the MIME header and footer
1197  * @param {ByteString} bin the binary data
1198  * @type String
1199  * @return the MIME/BASE64 encoded string
1200  */
1201 PKIXCommon.toPEM = function(label, bin) {
1202 	assert(typeof(label) == "string", "Parameter label must be string");
1203 	assert(bin instanceof ByteString, "Parameter bin must be ByteString");
1204 
1205 	var str = "-----BEGIN " + label + "-----\n";
1206 
1207 	var b64 = bin.toString(BASE64);
1208 	while(b64.length > 0) {
1209 		str += b64.substr(0, 64) + "\n";
1210 		b64 = b64.substr(64);
1211 	}
1212 
1213 	str += "-----END " + label + "-----\n";
1214 	return str;
1215 }
1216 
1217 
1218 
1219 /**
1220  * Parse PEM format and extract binary data
1221  *
1222  * @param {String} label the label of the section
1223  * @param {String} bin the binary data
1224  * @type String
1225  * @return the MIME/BASE64 encoded string
1226  */
1227 PKIXCommon.parsePEM = function(label, pem) {
1228 	assert(typeof(label) == "string", "Parameter label must be string");
1229 	assert(typeof(pem) == "string", "Parameter pem must be string");
1230 
1231 	var lines = pem.split("\n");
1232 
1233 	var b64str = "";
1234 	var parse = false;
1235 	for (var i = 0; i < lines.length; i++) {
1236 		var str = lines[i];
1237 
1238 		if (str == "-----BEGIN " + label + "-----") {
1239 			parse = true;
1240 		} else if (str == "-----END " + label + "-----") {
1241 			break;
1242 		} else if (parse) {
1243 			b64str += str;
1244 		}
1245 	}
1246 
1247 	return new ByteString(b64str, BASE64);
1248 }
1249 
1250 
1251 
1252 /**
1253  * Writes a byte string object to file
1254  *
1255  * <p>The filename is mapped to the workspace location.</p>
1256  *
1257  * @param {String} filename the fully qualified name of the file
1258  * @param {ByteString} content the content to write
1259  */
1260 PKIXCommon.writeFileToDisk = function(filename, content) {
1261 	var file = new java.io.FileOutputStream(filename);
1262 	file.write(content);
1263 	file.close();
1264 }
1265 
1266 
1267 
1268 /**
1269  * Loads a binary file from disk
1270  *
1271  * @param {String} filename the fully qualified file name
1272  * @return the binary content
1273  * @type ByteString
1274  */
1275 PKIXCommon.readFileFromDisk = function(filename) {
1276 	// Open stream
1277 	var f = new java.io.FileInputStream(filename);
1278 
1279 	// Determine file size
1280 	var flen = f.available();
1281 
1282 	// Allocate native byte array
1283 	var bs = java.lang.reflect.Array.newInstance(java.lang.Byte.TYPE, flen);
1284 
1285 	// Read into byte array
1286 	var len = f.read(bs);
1287 
1288 	f.close();
1289 
1290 	// Allocate JavaScript ByteBuffer from native/wrapped byte array
1291 	var bb = new ByteBuffer(bs);
1292 
1293 	// Convert to JavaScript ByteString
1294 	var data = bb.toByteString();
1295 
1296 	return data;
1297 }
1298 
1299 
1300 
1301 PKIXCommon.test = function() {
1302 	var issuer = { C:"C", O:"O", OU:"OU", SP:"SP", L:"L", DC:"DC", T:"T", G:"G", SN:"SN", CN:"CN", SERIALNUMBER:"serial", DNQ:"DNQ" };
1303 	var dn = PKIXCommon.encodeName(issuer);
1304 	print(dn);
1305 
1306 	var r = PKIXCommon.convertUnsignedInteger(new ByteString("00", HEX));
1307 	assert(r.toString(HEX) == "00");
1308 	var r = PKIXCommon.convertUnsignedInteger(new ByteString("80", HEX));
1309 	assert(r.toString(HEX) == "0080");
1310 	var r = PKIXCommon.convertUnsignedInteger(new ByteString("FF", HEX));
1311 	assert(r.toString(HEX) == "00FF");
1312 	var r = PKIXCommon.convertUnsignedInteger(new ByteString("0000", HEX));
1313 	assert(r.toString(HEX) == "00");
1314 	var r = PKIXCommon.convertUnsignedInteger(new ByteString("0080", HEX));
1315 	assert(r.toString(HEX) == "0080");
1316 	var r = PKIXCommon.convertUnsignedInteger(new ByteString("000080", HEX));
1317 	assert(r.toString(HEX) == "0080");
1318 }
1319