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 * Gets the signature algorithm TLV object 216 * 217 * @return the signature algorithm object 218 * @type ASN1 219 */ 220 PKIXCommon.encodeSignatureAlgorithm = function(signatureAlgorithm) { 221 var t = new ASN1("signatureAlgorithm", ASN1.SEQUENCE); 222 223 if ((signatureAlgorithm == Crypto.RSA) || (signatureAlgorithm == Crypto.RSA_SHA1)) { 224 t.add(new ASN1("algorithm", ASN1.OBJECT_IDENTIFIER, new ByteString("sha1WithRSAEncryption", OID))); 225 t.add(new ASN1("parameters", ASN1.NULL, new ByteString("", HEX))); 226 } else if (signatureAlgorithm == Crypto.RSA_SHA256) { 227 t.add(new ASN1("algorithm", ASN1.OBJECT_IDENTIFIER, new ByteString("sha256WithRSAEncryption", OID))); 228 t.add(new ASN1("parameters", ASN1.NULL, new ByteString("", HEX))); 229 } else if (signatureAlgorithm == Crypto.RSA_SHA384) { 230 t.add(new ASN1("algorithm", ASN1.OBJECT_IDENTIFIER, new ByteString("sha384WithRSAEncryption", OID))); 231 t.add(new ASN1("parameters", ASN1.NULL, new ByteString("", HEX))); 232 } else if (signatureAlgorithm == Crypto.RSA_SHA512) { 233 t.add(new ASN1("algorithm", ASN1.OBJECT_IDENTIFIER, new ByteString("sha512WithRSAEncryption", OID))); 234 t.add(new ASN1("parameters", ASN1.NULL, new ByteString("", HEX))); 235 } else if (signatureAlgorithm == Crypto.RSA_PSS_SHA1) { 236 t.add(new ASN1("algorithm", ASN1.OBJECT_IDENTIFIER, new ByteString("id-RSASSA-PSS", OID))); 237 t.add(new ASN1("parameters", ASN1.NULL, new ByteString("", HEX))); 238 } else if (signatureAlgorithm == Crypto.ECDSA_SHA1) { 239 t.add(new ASN1("algorithm", ASN1.OBJECT_IDENTIFIER, new ByteString("ecdsa-with-SHA1", OID))); 240 t.add(new ASN1("parameters", ASN1.NULL, new ByteString("", HEX))); 241 } else if (signatureAlgorithm == Crypto.ECDSA_SHA224) { 242 t.add(new ASN1("algorithm", ASN1.OBJECT_IDENTIFIER, new ByteString("ecdsa-with-SHA224", OID))); 243 t.add(new ASN1("parameters", ASN1.NULL, new ByteString("", HEX))); 244 } else if (signatureAlgorithm == Crypto.ECDSA_SHA256) { 245 t.add(new ASN1("algorithm", ASN1.OBJECT_IDENTIFIER, new ByteString("ecdsa-with-SHA256", OID))); 246 t.add(new ASN1("parameters", ASN1.NULL, new ByteString("", HEX))); 247 } else if (signatureAlgorithm == Crypto.ECDSA_SHA384) { 248 t.add(new ASN1("algorithm", ASN1.OBJECT_IDENTIFIER, new ByteString("ecdsa-with-SHA384", OID))); 249 t.add(new ASN1("parameters", ASN1.NULL, new ByteString("", HEX))); 250 } else if (signatureAlgorithm == Crypto.ECDSA_SHA512) { 251 t.add(new ASN1("algorithm", ASN1.OBJECT_IDENTIFIER, new ByteString("ecdsa-with-SHA512", OID))); 252 t.add(new ASN1("parameters", ASN1.NULL, new ByteString("", HEX))); 253 } else { 254 throw new GPError(module.id, GPError.INVALID_MECH, signatureAlgorithm, "Invalid algorithm"); 255 } 256 257 return t; 258 } 259 260 261 262 PKIXCommon.algIdMap = {}; 263 PKIXCommon.algIdMap[(new ByteString("sha1WithRSAEncryption", OID)).toString(HEX)] = Crypto.RSA_SHA1; 264 PKIXCommon.algIdMap[(new ByteString("sha256WithRSAEncryption", OID)).toString(HEX)] = Crypto.RSA_SHA256; 265 PKIXCommon.algIdMap[(new ByteString("sha384WithRSAEncryption", OID)).toString(HEX)] = Crypto.RSA_SHA384; 266 PKIXCommon.algIdMap[(new ByteString("sha512WithRSAEncryption", OID)).toString(HEX)] = Crypto.RSA_SHA512; 267 PKIXCommon.algIdMap[(new ByteString("id-RSASSA-PSS", OID)).toString(HEX)] = Crypto.RSA_PSS_SHA1; 268 PKIXCommon.algIdMap[(new ByteString("ecdsa-with-SHA1", OID)).toString(HEX)] = Crypto.ECDSA_SHA1; 269 PKIXCommon.algIdMap[(new ByteString("ecdsa-with-SHA224", OID)).toString(HEX)] = Crypto.ECDSA_SHA224; 270 PKIXCommon.algIdMap[(new ByteString("ecdsa-with-SHA256", OID)).toString(HEX)] = Crypto.ECDSA_SHA256; 271 PKIXCommon.algIdMap[(new ByteString("ecdsa-with-SHA384", OID)).toString(HEX)] = Crypto.ECDSA_SHA384; 272 PKIXCommon.algIdMap[(new ByteString("ecdsa-with-SHA512", OID)).toString(HEX)] = Crypto.ECDSA_SHA512; 273 274 275 276 /** 277 * Return Crypto.x constant for given signatureAlgorithm 278 * 279 * @param {ByteString} signatureAlgorithm the algorithm 280 * @type Number 281 * @return the Crypto.X constant 282 */ 283 PKIXCommon.decodeSignatureAlgorithm = function(signatureAlgorithm) { 284 var alg = PKIXCommon.algIdMap[signatureAlgorithm.toString(HEX)]; 285 return alg; 286 } 287 288 289 290 /** 291 * Return Crypto.RSA or Crypto.EC depending on signature algorithm 292 * 293 * @param {Number} alg signature algorithm (one of Crypto.X) 294 * @type Number 295 * @return either Crypto.RSA or Crypto.EC 296 */ 297 PKIXCommon.keyTypeForAlgorithm = function(alg) { 298 if ((alg == Crypto.RSA) || 299 (alg == Crypto.RSA_SHA256) || 300 (alg == Crypto.RSA_SHA384) || 301 (alg == Crypto.RSA_SHA512) || 302 (alg == Crypto.RSA_PSS_SHA1)) { 303 return Crypto.RSA; 304 } else { 305 return Crypto.EC; 306 } 307 } 308 309 310 311 /** 312 * Creates the EC Public Key as subjectPublicKeyInfo TLV structure object. 313 * 314 * <p>The structure is defined as:</p> 315 * <pre> 316 * SubjectPublicKeyInfo ::= SEQUENCE { 317 * algorithm AlgorithmIdentifier, 318 * subjectPublicKey BIT STRING } 319 * 320 * AlgorithmIdentifier ::= SEQUENCE { 321 * algorithm OBJECT IDENTIFIER, 322 * parameters ANY DEFINED BY algorithm OPTIONAL } 323 * 324 * id-ecPublicKey OBJECT IDENTIFIER ::= { 325 * iso(1) member-body(2) us(840) ansi-X9-62(10045) keyType(2) 1 } 326 * 327 * ECParameters ::= CHOICE { 328 * namedCurve OBJECT IDENTIFIER, 329 * implicitCurve NULL, 330 * specifiedCurve SpecifiedECDomain } 331 * </pre> 332 * @return the subjectPublicKey TLV structure 333 * @type ASN1 334 */ 335 PKIXCommon.createECSubjectPublicKeyInfo = function(publicKey, encodeECDomainParameter) { 336 var t = new ASN1("subjectPublicKeyInfo", ASN1.SEQUENCE); 337 338 var algorithm = new ASN1("algorithm", ASN1.SEQUENCE, 339 new ASN1("algorithm", ASN1.OBJECT_IDENTIFIER, new ByteString("id-ecPublicKey", OID)) 340 ); 341 342 if (encodeECDomainParameter) { 343 if (!publicKey.getComponent(Key.ECC_P)) { // Make sure curve components are available if only curve oid is defined 344 publicKey.setComponent(Key.ECC_CURVE_OID, publicKey.getComponent(Key.ECC_CURVE_OID)); 345 } 346 var ecParameter = 347 new ASN1("ecParameters", ASN1.SEQUENCE, 348 new ASN1("version", ASN1.INTEGER, new ByteString("01", HEX)), 349 new ASN1("fieldID", ASN1.SEQUENCE, 350 new ASN1("fieldType", ASN1.OBJECT_IDENTIFIER, new ByteString("prime-field", OID)), 351 new ASN1("prime", ASN1.INTEGER, 352 PKIXCommon.convertUnsignedInteger(publicKey.getComponent(Key.ECC_P))) 353 ), 354 new ASN1("curve", ASN1.SEQUENCE, 355 new ASN1("a", ASN1.OCTET_STRING, publicKey.getComponent(Key.ECC_A)), 356 new ASN1("b", ASN1.OCTET_STRING, publicKey.getComponent(Key.ECC_B)) 357 ), 358 new ASN1("base", ASN1.OCTET_STRING, 359 (new ByteString("04", HEX)).concat(publicKey.getComponent(Key.ECC_GX)).concat(publicKey.getComponent(Key.ECC_GY))), 360 new ASN1("order", ASN1.INTEGER, 361 PKIXCommon.convertUnsignedInteger(publicKey.getComponent(Key.ECC_N))) 362 ); 363 364 var cofactor = publicKey.getComponent(Key.ECC_H); 365 var i = 0; 366 for (; (i < cofactor.length) && (cofactor.byteAt(i) == 0); i++); 367 if (i < cofactor.length) { 368 ecParameter.add(new ASN1("cofactor", ASN1.INTEGER, cofactor.bytes(i))); 369 } 370 algorithm.add(ecParameter); 371 } else { 372 algorithm.add(new ASN1("parameters", ASN1.OBJECT_IDENTIFIER, publicKey.getComponent(Key.ECC_CURVE_OID))); 373 } 374 375 t.add(algorithm); 376 377 // Prefix a 00 to form correct bitstring 378 // Prefix a 04 to indicate uncompressed format 379 var keybin = new ByteString("0004", HEX); 380 keybin = keybin.concat(publicKey.getComponent(Key.ECC_QX)); 381 keybin = keybin.concat(publicKey.getComponent(Key.ECC_QY)); 382 t.add(new ASN1("subjectPublicKey", ASN1.BIT_STRING, keybin)); 383 384 return t; 385 } 386 387 388 389 /** 390 * Creates the RSA Public Key as subjectPublicKeyInfo TLV structure object. 391 * 392 * <p>The structure is defined as:</p> 393 * <pre> 394 * SubjectPublicKeyInfo ::= SEQUENCE { 395 * algorithm AlgorithmIdentifier, 396 * subjectPublicKey BIT STRING } 397 * 398 * AlgorithmIdentifier ::= SEQUENCE { 399 * algorithm OBJECT IDENTIFIER, 400 * parameters ANY DEFINED BY algorithm OPTIONAL } 401 * 402 * pkcs-1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 } 403 * 404 * rsaEncryption OBJECT IDENTIFIER ::= { pkcs-1 1} 405 * 406 * RSAPublicKey ::= SEQUENCE { 407 * modulus INTEGER, -- n 408 * publicExponent INTEGER } -- e 409 * </pre> 410 * 411 * @return the subjectPublicKey TLV structure 412 * @type ASN1 413 */ 414 PKIXCommon.createRSASubjectPublicKeyInfo = function(publicKey) { 415 var t = new ASN1("subjectPublicKeyInfo", ASN1.SEQUENCE); 416 417 t.add(new ASN1("algorithm", ASN1.SEQUENCE, 418 new ASN1("algorithm", ASN1.OBJECT_IDENTIFIER, new ByteString("rsaEncryption", OID)), 419 new ASN1("parameters", ASN1.NULL, new ByteString("", HEX)) 420 )); 421 // Prefix a 00 to form correct bitstring 422 var keybin = new ByteString("00", HEX); 423 424 var modulus = publicKey.getComponent(Key.MODULUS); 425 modulus = PKIXCommon.convertUnsignedInteger(modulus); 426 427 var exponent = publicKey.getComponent(Key.EXPONENT); 428 exponent = PKIXCommon.convertUnsignedInteger(exponent); 429 430 var rsapub = new ASN1("RSAPublicKey", ASN1.SEQUENCE, 431 new ASN1("modulus", ASN1.INTEGER, modulus), 432 new ASN1("publicKeyExponent", ASN1.INTEGER, exponent)); 433 434 keybin = keybin.concat(rsapub.getBytes()); 435 t.add(new ASN1("subjectPublicKey", ASN1.BIT_STRING, keybin)); 436 437 return t; 438 } 439 440 441 442 /** 443 * Determine key identifier according to RFC5280 using SHA-1 over the SubjectPublicKeyInfo 444 * 445 * @param {Key} publicKey the public key 446 * @param {Boolean} encodeECDomainParameter true to include domain parameter in SPKI of EC key 447 */ 448 PKIXCommon.determineKeyIdentifier = function(publicKey, encodeECDomainParameter) { 449 if (typeof(encodeECDomainParameter) == "undefined") { 450 encodeECDomainParameter = true; 451 } 452 453 var spki; 454 455 if (publicKey.getComponent(Key.MODULUS)) { 456 spki = PKIXCommon.createRSASubjectPublicKeyInfo(publicKey); 457 } else { 458 spki = PKIXCommon.createECSubjectPublicKeyInfo(publicKey, encodeECDomainParameter); 459 } 460 461 var keyvalue = spki.get(1).value.bytes(1); 462 var crypto = new Crypto(); 463 return (crypto.digest(Crypto.SHA_1, keyvalue)); 464 } 465 466 467 468 /** 469 * Creates a relative distinguished name component. 470 * 471 * <p>The structure is defined as:</p> 472 * <pre> 473 * RelativeDistinguishedName ::= 474 * SET SIZE (1..MAX) OF AttributeTypeAndValue 475 * 476 * AttributeTypeAndValue ::= SEQUENCE { 477 * type AttributeType, 478 * value AttributeValue } 479 * 480 * AttributeType ::= OBJECT IDENTIFIER 481 * 482 * AttributeValue ::= ANY -- DEFINED BY AttributeType 483 * 484 * DirectoryString ::= CHOICE { 485 * teletexString TeletexString (SIZE (1..MAX)), 486 * printableString PrintableString (SIZE (1..MAX)), 487 * universalString UniversalString (SIZE (1..MAX)), 488 * utf8String UTF8String (SIZE (1..MAX)), 489 * bmpString BMPString (SIZE (1..MAX)) } 490 *</pre> 491 * 492 * @param {String} name the components name 493 * @param {String} oid the oid for the RDN 494 * @param {ASN1} value the value object 495 * @return the 496 */ 497 PKIXCommon.makeRDN = function(name, oid, value) { 498 return new ASN1(name, ASN1.SET, 499 new ASN1(ASN1.SEQUENCE, 500 new ASN1(ASN1.OBJECT_IDENTIFIER, new ByteString(oid, OID)), 501 value 502 ) 503 ); 504 } 505 506 507 508 /** 509 * Adds names from the name object to the RDNSequence. 510 * 511 * @param {ASN1} t the sequence object 512 * @param {Object} name the name object 513 */ 514 PKIXCommon.addNames = function(t, name) { 515 if (name.C) { 516 t.add(PKIXCommon.makeRDN("country", "id-at-countryName", new ASN1(ASN1.PrintableString, new ByteString(name.C, ASCII)))); 517 } 518 if (name.ST) { 519 t.add(PKIXCommon.makeRDN("stateOrProvinceName", "id-at-stateOrProvinceName", new ASN1(ASN1.UTF8String, new ByteString(name.O, UTF8)))); 520 } 521 if (name.O) { 522 t.add(PKIXCommon.makeRDN("organization", "id-at-organizationName", new ASN1(ASN1.UTF8String, new ByteString(name.O, UTF8)))); 523 } 524 if (name.OU) { 525 t.add(PKIXCommon.makeRDN("organizationalUnit", "id-at-organizationalUnitName", new ASN1(ASN1.UTF8String, new ByteString(name.OU, UTF8)))); 526 } 527 if (name.S) { 528 t.add(PKIXCommon.makeRDN("stateOrProvince", "id-at-stateOrProvinceName", new ASN1(ASN1.UTF8String, new ByteString(name.S, UTF8)))); 529 } 530 if (name.L) { 531 t.add(PKIXCommon.makeRDN("locality", "id-at-localityName", new ASN1(ASN1.UTF8String, new ByteString(name.L, UTF8)))); 532 } 533 if (name.DC) { 534 t.add(PKIXCommon.makeRDN("domainComponent", "id-domainComponent", new ASN1(ASN1.UTF8String, new ByteString(name.DC, UTF8)))); 535 } 536 if (name.T) { 537 t.add(PKIXCommon.makeRDN("title", "id-at-title", new ASN1(ASN1.UTF8String, new ByteString(name.T, UTF8)))); 538 } 539 if (name.G) { 540 t.add(PKIXCommon.makeRDN("givenName", "id-at-givenName", new ASN1(ASN1.UTF8String, new ByteString(name.G, UTF8)))); 541 } 542 if (name.SN) { 543 t.add(PKIXCommon.makeRDN("surname", "id-at-surname", new ASN1(ASN1.UTF8String, new ByteString(name.SN, UTF8)))); 544 } 545 if (name.CN) { 546 t.add(PKIXCommon.makeRDN("commonName", "id-at-commonName", new ASN1(ASN1.UTF8String, new ByteString(name.CN, UTF8)))); 547 } 548 if (name.SERIALNUMBER) { 549 t.add(PKIXCommon.makeRDN("serialNumber", "id-at-serialNumber", new ASN1(ASN1.UTF8String, new ByteString(name.SERIALNUMBER, UTF8)))); 550 } 551 if (name.DNQ) { 552 t.add(PKIXCommon.makeRDN("dnQualifier", "id-at-dnQualifier", new ASN1(ASN1.UTF8String, new ByteString(name.DNQ, UTF8)))); 553 } 554 if (name.E) { 555 t.add(PKIXCommon.makeRDN("emailAddress", "id-emailAddress", new ASN1(ASN1.IA5String, new ByteString(name.E, ASCII)))); 556 } 557 if (name.UID) { 558 t.add(PKIXCommon.makeRDN("userId", "id-userId", new ASN1(ASN1.UTF8String, new ByteString(name.UID, UTF8)))); 559 } 560 } 561 562 563 564 PKIXCommon.validRDN = [ "C","ST", "O","OU","S","L","DC","T","G","SN","CN","SERIALNUMBER","DNQ","E","UID" ]; 565 566 /** 567 * Gets the dn as TLV object 568 * 569 * <p>This function support two format for names</p> 570 * <pre> 571 * var issuer = { C:"UT", O:"ACME Corporation", CN:"Test-CA" }; 572 * or 573 * var issuer = [ { C:"UT"}, { O:"ACME Corporation" }, { CN:"Test-CA"} ]; 574 * </pre> 575 * 576 * <p>It supports the following RDNs:</p> 577 * <ul> 578 * <li>C - country</li> 579 * <li>ST - state</li> 580 * <li>O - organization</li> 581 * <li>OU - organizational unit</li> 582 * <li>S - state or province</li> 583 * <li>L - locality</li> 584 * <li>DC - domain component</li> 585 * <li>T - title</li> 586 * <li>G - given name</li> 587 * <li>SN - surname</li> 588 * <li>CN - common name</li> 589 * <li>SERIALNUMBER - serial number</li> 590 * <li>DNQ - domain name qualifier</li> 591 * <li>E - e-mail address</li> 592 * <li>UID - user Id</li> 593 * <p>The first format sorts the RDS in the sequence C,ST,O,OU,S,L,DC,T,G,SN,CN,SERIALNUMBER,DNQ,E,UID</p> 594 * </ul> 595 * @param {Object} name the name object 596 * @return the RDNSequence 597 * @type ASN1 598 */ 599 PKIXCommon.encodeName = function(name) { 600 var t = new ASN1("subject", ASN1.SEQUENCE); 601 if (typeof(name.C) == "undefined") { 602 for (var i = 0; i < name.length; i++) { 603 PKIXCommon.addNames(t, name[i]); 604 } 605 } else { 606 PKIXCommon.addNames(t, name); 607 } 608 return t; 609 } 610 611 612 613 PKIXCommon.parseDN = function(dn) { 614 assert(typeof(dn) == "string", "Parameter dn must be string"); 615 616 var e = dn.split(","); 617 var rdnlist = []; 618 619 for (var i = 0; i < e.length; i++) { 620 var p = e[i].split("="); 621 622 if (p.length < 2) { 623 throw new GPError(module.id, GPError.INVALID_DATA, i, "Missing '=' in RDN " + e[i]); 624 } 625 626 if (p.length > 2) { 627 throw new GPError(module.id, GPError.INVALID_DATA, i, "Too many '=' in RDN " + e[i]); 628 } 629 630 var key = p[0].trim().toUpperCase(); 631 632 if (key.length == 0) { 633 throw new GPError(module.id, GPError.INVALID_DATA, i, "Key in RDN " + e[i] + " can't be empty"); 634 } 635 636 if (PKIXCommon.validRDN.indexOf(key) == -1) { 637 throw new GPError(module.id, GPError.INVALID_DATA, i, key + " is not a supported RDN (Valid RDNs are " + PKIXCommon.validRDN + ")"); 638 } 639 640 var value = p[1].trim(); 641 642 if (value.length == 0) { 643 throw new GPError(module.id, GPError.INVALID_DATA, i, "Value for " + key + " can't be empty"); 644 } 645 var rdn = { }; 646 rdn[key] = value; 647 rdnlist.push(rdn); 648 } 649 return rdnlist; 650 } 651 652 653 654 /** 655 * Convert a DN parsed with parseDN() back into the string format 656 * 657 * @param {Object[]} dn the dn array 658 * @type String 659 * @return the DN in string format 660 */ 661 PKIXCommon.dnToString = function(dn) { 662 var str = ""; 663 664 for (var i = 0; i < dn.length; i++) { 665 if (str.length > 0) { 666 str += ","; 667 } 668 669 for (var j in dn[i]) { 670 str += j + "=" + dn[i][j]; 671 } 672 } 673 return str; 674 } 675 676 677 678 PKIXCommon.findRDN = function(rdnlist, c) { 679 for (var i = 0; i < rdnlist.length; i++) { 680 var v = rdnlist[i][c]; 681 if (v) { 682 return v; 683 } 684 } 685 } 686 687 688 689 PKIXCommon.countryNames = { 690 AF:"Afghanistan", 691 AX:"Aeland Islands", 692 AL:"Albania", 693 DZ:"Algeria", 694 AS:"American Samoa", 695 AD:"Andorra", 696 AO:"Angola", 697 AI:"Anguilla", 698 AQ:"Antarctica", 699 AG:"Antigua and Barbuda", 700 AR:"Argentina", 701 AM:"Armenia", 702 AW:"Aruba", 703 AU:"Australia", 704 AT:"Austria", 705 AZ:"Azerbaijan", 706 BS:"Bahamas", 707 BH:"Bahrain", 708 BD:"Bangladesh", 709 BB:"Barbados", 710 BY:"Belarus", 711 BE:"Belgium", 712 BZ:"Belize", 713 BJ:"Benin", 714 BM:"Bermuda", 715 BT:"Bhutan", 716 BO:"Bolivia, Plurinational State of", 717 BQ:"Bonaire, Sint Eustatius and Saba", 718 BA:"Bosnia and Herzegovina", 719 BW:"Botswana", 720 BV:"Bouvet Island", 721 BR:"Brazil", 722 IO:"British Indian Ocean Territory", 723 BN:"Brunei Darussalam", 724 BG:"Bulgaria", 725 BF:"Burkina Faso", 726 BI:"Burundi", 727 KH:"Cambodia", 728 CM:"Cameroon", 729 CA:"Canada", 730 CV:"Cape Verde", 731 KY:"Cayman Islands", 732 CF:"Central African Republic", 733 TD:"Chad", 734 CL:"Chile", 735 CN:"China", 736 CX:"Christmas Island", 737 CC:"Cocos (Keeling) Islands", 738 CO:"Colombia", 739 KM:"Comoros", 740 CG:"Congo", 741 CD:"Congo, the Democratic Republic of the", 742 CK:"Cook Islands", 743 CR:"Costa Rica", 744 CI:"Cote d'Ivoire", 745 HR:"Croatia", 746 CU:"Cuba", 747 CW:"Curacao", 748 CY:"Cyprus", 749 CZ:"Czech Republic", 750 DK:"Denmark", 751 DJ:"Djibouti", 752 DM:"Dominica", 753 DO:"Dominican Republic", 754 EC:"Ecuador", 755 EG:"Egypt", 756 SV:"El Salvador", 757 GQ:"Equatorial Guinea", 758 ER:"Eritrea", 759 EE:"Estonia", 760 ET:"Ethiopia", 761 FK:"Falkland Islands (Malvinas)", 762 FO:"Faroe Islands", 763 FJ:"Fiji", 764 FI:"Finland", 765 FR:"France", 766 GF:"French Guiana", 767 PF:"French Polynesia", 768 TF:"French Southern Territories", 769 GA:"Gabon", 770 GM:"Gambia", 771 GE:"Georgia", 772 DE:"Germany", 773 GH:"Ghana", 774 GI:"Gibraltar", 775 GR:"Greece", 776 GL:"Greenland", 777 GD:"Grenada", 778 GP:"Guadeloupe", 779 GU:"Guam", 780 GT:"Guatemala", 781 GG:"Guernsey", 782 GN:"Guinea", 783 GW:"Guinea-Bissau", 784 GY:"Guyana", 785 HT:"Haiti", 786 HM:"Heard Island and McDonald Islands", 787 VA:"Holy See (Vatican City State)", 788 HN:"Honduras", 789 HK:"Hong Kong", 790 HU:"Hungary", 791 IS:"Iceland", 792 IN:"India", 793 ID:"Indonesia", 794 IR:"Iran, Islamic Republic of", 795 IQ:"Iraq", 796 IE:"Ireland", 797 IM:"Isle of Man", 798 IL:"Israel", 799 IT:"Italy", 800 JM:"Jamaica", 801 JP:"Japan", 802 JE:"Jersey", 803 JO:"Jordan", 804 KZ:"Kazakhstan", 805 KE:"Kenya", 806 KI:"Kiribati", 807 KP:"Korea, Democratic People's Republic of", 808 KR:"Korea, Republic of", 809 KW:"Kuwait", 810 KG:"Kyrgyzstan", 811 LA:"Lao People's Democratic Republic", 812 LV:"Latvia", 813 LB:"Lebanon", 814 LS:"Lesotho", 815 LR:"Liberia", 816 LY:"Libya", 817 LI:"Liechtenstein", 818 LT:"Lithuania", 819 LU:"Luxembourg", 820 MO:"Macao", 821 MK:"Macedonia, the Former Yugoslav Republic of", 822 MG:"Madagascar", 823 MW:"Malawi", 824 MY:"Malaysia", 825 MV:"Maldives", 826 ML:"Mali", 827 MT:"Malta", 828 MH:"Marshall Islands", 829 MQ:"Martinique", 830 MR:"Mauritania", 831 MU:"Mauritius", 832 YT:"Mayotte", 833 MX:"Mexico", 834 FM:"Micronesia, Federated States of", 835 MD:"Moldova, Republic of", 836 MC:"Monaco", 837 MN:"Mongolia", 838 ME:"Montenegro", 839 MS:"Montserrat", 840 MA:"Morocco", 841 MZ:"Mozambique", 842 MM:"Myanmar", 843 NA:"Namibia", 844 NR:"Nauru", 845 NP:"Nepal", 846 NL:"Netherlands", 847 NC:"New Caledonia", 848 NZ:"New Zealand", 849 NI:"Nicaragua", 850 NE:"Niger", 851 NG:"Nigeria", 852 NU:"Niue", 853 NF:"Norfolk Island", 854 MP:"Northern Mariana Islands", 855 NO:"Norway", 856 OM:"Oman", 857 PK:"Pakistan", 858 PW:"Palau", 859 PS:"Palestine, State of", 860 PA:"Panama", 861 PG:"Papua New Guinea", 862 PY:"Paraguay", 863 PE:"Peru", 864 PH:"Philippines", 865 PN:"Pitcairn", 866 PL:"Poland", 867 PT:"Portugal", 868 PR:"Puerto Rico", 869 QA:"Qatar", 870 RE:"Reunion", 871 RO:"Romania", 872 RU:"Russian Federation", 873 RW:"Rwanda", 874 BL:"Saint Bartholemy", 875 SH:"Saint Helena, Ascension and Tristan da Cunha", 876 KN:"Saint Kitts and Nevis", 877 LC:"Saint Lucia", 878 MF:"Saint Martin (French part)", 879 PM:"Saint Pierre and Miquelon", 880 VC:"Saint Vincent and the Grenadines", 881 WS:"Samoa", 882 SM:"San Marino", 883 ST:"Sao Tome and Principe", 884 SA:"Saudi Arabia", 885 SN:"Senegal", 886 RS:"Serbia", 887 SC:"Seychelles", 888 SL:"Sierra Leone", 889 SG:"Singapore", 890 SX:"Sint Maarten (Dutch part)", 891 SK:"Slovakia", 892 SI:"Slovenia", 893 SB:"Solomon Islands", 894 SO:"Somalia", 895 ZA:"South Africa", 896 GS:"South Georgia and the South Sandwich Islands", 897 SS:"South Sudan", 898 ES:"Spain", 899 LK:"Sri Lanka", 900 SD:"Sudan", 901 SR:"Suriname", 902 SJ:"Svalbard and Jan Mayen", 903 SZ:"Swaziland", 904 SE:"Sweden", 905 CH:"Switzerland", 906 SY:"Syrian Arab Republic", 907 TW:"Taiwan, Province of China", 908 TJ:"Tajikistan", 909 TZ:"Tanzania, United Republic of", 910 TH:"Thailand", 911 TL:"Timor-Leste", 912 TG:"Togo", 913 TK:"Tokelau", 914 TO:"Tonga", 915 TT:"Trinidad and Tobago", 916 TN:"Tunisia", 917 TR:"Turkey", 918 TM:"Turkmenistan", 919 TC:"Turks and Caicos Islands", 920 TV:"Tuvalu", 921 UG:"Uganda", 922 UA:"Ukraine", 923 AE:"United Arab Emirates", 924 GB:"United Kingdom", 925 US:"United States", 926 UM:"United States Minor Outlying Islands", 927 UY:"Uruguay", 928 UZ:"Uzbekistan", 929 VU:"Vanuatu", 930 VE:"Venezuela, Bolivarian Republic of", 931 VN:"Viet Nam", 932 VG:"Virgin Islands, British", 933 VI:"Virgin Islands, U.S.", 934 WF:"Wallis and Futuna", 935 EH:"Western Sahara", 936 YE:"Yemen", 937 ZM:"Zambia", 938 ZW:"Zimbabwe" 939 }; 940 941 942 943 /** 944 * Extract subject from certificate as ASN1 object 945 * 946 * @param {X509} cert the certificate 947 * @type ASN1 948 * @return the subject as ASN1 949 */ 950 PKIXCommon.getSubjectAsASN1 = function(cert) { 951 var a = new ASN1(cert.getBytes()); 952 return a.get(0).get(5); 953 } 954 955 956 957 /** 958 * Extract issuer from certificate as ASN1 object 959 * 960 * @param {X509} cert the certificate 961 * @type ASN1 962 * @return the issuer as ASN1 963 */ 964 PKIXCommon.getIssuerAsASN1 = function(cert) { 965 var a = new ASN1(cert.getBytes()); 966 return a.get(0).get(3); 967 } 968 969 970 971 /** 972 * Convert binary data to PEM format 973 * 974 * @param {String} label the label to be used in the MIME header and footer 975 * @param {ByteString} bin the binary data 976 * @type String 977 * @return the MIME/BASE64 encoded string 978 */ 979 PKIXCommon.toPEM = function(label, bin) { 980 assert(typeof(label) == "string", "Parameter label must be string"); 981 assert(bin instanceof ByteString, "Parameter bin must be ByteString"); 982 983 var str = "-----BEGIN " + label + "-----\n"; 984 985 var b64 = bin.toString(BASE64); 986 while(b64.length > 0) { 987 str += b64.substr(0, 64) + "\n"; 988 b64 = b64.substr(64); 989 } 990 991 str += "-----END " + label + "-----\n"; 992 return str; 993 } 994 995 996 997 /** 998 * Parse PEM format and extract binary data 999 * 1000 * @param {String} label the label of the section 1001 * @param {ByteString} bin the binary data 1002 * @type String 1003 * @return the MIME/BASE64 encoded string 1004 */ 1005 PKIXCommon.parsePEM = function(label, pem) { 1006 assert(typeof(label) == "string", "Parameter label must be string"); 1007 assert(typeof(pem) == "string", "Parameter pem must be string"); 1008 1009 var lines = pem.split("\n"); 1010 1011 var b64str = ""; 1012 var parse = false; 1013 for (var i = 0; i < lines.length; i++) { 1014 var str = lines[i]; 1015 1016 if (str == "-----BEGIN " + label + "-----") { 1017 parse = true; 1018 } else if (str == "-----END " + label + "-----") { 1019 break; 1020 } else if (parse) { 1021 b64str += str; 1022 } 1023 } 1024 1025 return new ByteString(b64str, BASE64); 1026 } 1027 1028 1029 1030 /** 1031 * Writes a byte string object to file 1032 * 1033 * <p>The filename is mapped to the workspace location.</p> 1034 * 1035 * @param {String} filename the fully qualified name of the file 1036 * @param {ByteString} content the content to write 1037 */ 1038 PKIXCommon.writeFileToDisk = function(filename, content) { 1039 var file = new java.io.FileOutputStream(filename); 1040 file.write(content); 1041 file.close(); 1042 } 1043 1044 1045 1046 /** 1047 * Loads a binary file from disk 1048 * 1049 * @param {String} filename the fully qualified file name 1050 * @return the binary content 1051 * @type ByteString 1052 */ 1053 PKIXCommon.readFileFromDisk = function(filename) { 1054 // Open stream 1055 var f = new java.io.FileInputStream(filename); 1056 1057 // Determine file size 1058 var flen = f.available(); 1059 1060 // Allocate native byte array 1061 var bs = java.lang.reflect.Array.newInstance(java.lang.Byte.TYPE, flen); 1062 1063 // Read into byte array 1064 var len = f.read(bs); 1065 1066 f.close(); 1067 1068 // Allocate JavaScript ByteBuffer from native/wrapped byte array 1069 var bb = new ByteBuffer(bs); 1070 1071 // Convert to JavaScript ByteString 1072 var data = bb.toByteString(); 1073 1074 return data; 1075 } 1076 1077 1078 1079 PKIXCommon.test = function() { 1080 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" }; 1081 var dn = PKIXCommon.encodeName(issuer); 1082 print(dn); 1083 1084 var r = PKIXCommon.convertUnsignedInteger(new ByteString("00", HEX)); 1085 assert(r.toString(HEX) == "00"); 1086 var r = PKIXCommon.convertUnsignedInteger(new ByteString("80", HEX)); 1087 assert(r.toString(HEX) == "0080"); 1088 var r = PKIXCommon.convertUnsignedInteger(new ByteString("FF", HEX)); 1089 assert(r.toString(HEX) == "00FF"); 1090 var r = PKIXCommon.convertUnsignedInteger(new ByteString("0000", HEX)); 1091 assert(r.toString(HEX) == "00"); 1092 var r = PKIXCommon.convertUnsignedInteger(new ByteString("0080", HEX)); 1093 assert(r.toString(HEX) == "0080"); 1094 var r = PKIXCommon.convertUnsignedInteger(new ByteString("000080", HEX)); 1095 assert(r.toString(HEX) == "0080"); 1096 } 1097