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 /** 614 * Return the value of the last RDN 615 * 616 * @param {Object[]} dn the dn array 617 * @type String 618 * @return the value of the last RDN 619 */ 620 PKIXCommon.makeName = function(rdnlist) { 621 if (rdnlist.length == 0) { 622 return undefined; 623 } 624 var l = rdnlist[rdnlist.length - 1]; 625 626 for (var i in l) { 627 return l[i]; 628 } 629 630 return undefined; 631 } 632 633 634 635 PKIXCommon.parseDN = function(dn) { 636 assert(typeof(dn) == "string", "Parameter dn must be string"); 637 638 var e = dn.split(","); 639 var rdnlist = []; 640 641 for (var i = 0; i < e.length; i++) { 642 var p = e[i].split("="); 643 644 if (p.length < 2) { 645 throw new GPError(module.id, GPError.INVALID_DATA, i, "Missing '=' in RDN " + e[i]); 646 } 647 648 if (p.length > 2) { 649 throw new GPError(module.id, GPError.INVALID_DATA, i, "Too many '=' in RDN " + e[i]); 650 } 651 652 var key = p[0].trim().toUpperCase(); 653 654 if (key.length == 0) { 655 throw new GPError(module.id, GPError.INVALID_DATA, i, "Key in RDN " + e[i] + " can't be empty"); 656 } 657 658 if (PKIXCommon.validRDN.indexOf(key) == -1) { 659 throw new GPError(module.id, GPError.INVALID_DATA, i, key + " is not a supported RDN (Valid RDNs are " + PKIXCommon.validRDN + ")"); 660 } 661 662 var value = p[1].trim(); 663 664 if (value.length == 0) { 665 throw new GPError(module.id, GPError.INVALID_DATA, i, "Value for " + key + " can't be empty"); 666 } 667 var rdn = { }; 668 rdn[key] = value; 669 rdnlist.push(rdn); 670 } 671 return rdnlist; 672 } 673 674 675 676 /** 677 * Convert a DN parsed with parseDN() back into the string format 678 * 679 * @param {Object[]} dn the dn array 680 * @type String 681 * @return the DN in string format 682 */ 683 PKIXCommon.dnToString = function(dn) { 684 var str = ""; 685 686 for (var i = 0; i < dn.length; i++) { 687 if (str.length > 0) { 688 str += ","; 689 } 690 691 for (var j in dn[i]) { 692 str += j + "=" + dn[i][j]; 693 } 694 } 695 return str; 696 } 697 698 699 700 PKIXCommon.findRDN = function(rdnlist, c) { 701 for (var i = 0; i < rdnlist.length; i++) { 702 var v = rdnlist[i][c]; 703 if (v) { 704 return v; 705 } 706 } 707 } 708 709 710 711 PKIXCommon.countryNames = { 712 AF:"Afghanistan", 713 AX:"Aeland Islands", 714 AL:"Albania", 715 DZ:"Algeria", 716 AS:"American Samoa", 717 AD:"Andorra", 718 AO:"Angola", 719 AI:"Anguilla", 720 AQ:"Antarctica", 721 AG:"Antigua and Barbuda", 722 AR:"Argentina", 723 AM:"Armenia", 724 AW:"Aruba", 725 AU:"Australia", 726 AT:"Austria", 727 AZ:"Azerbaijan", 728 BS:"Bahamas", 729 BH:"Bahrain", 730 BD:"Bangladesh", 731 BB:"Barbados", 732 BY:"Belarus", 733 BE:"Belgium", 734 BZ:"Belize", 735 BJ:"Benin", 736 BM:"Bermuda", 737 BT:"Bhutan", 738 BO:"Bolivia, Plurinational State of", 739 BQ:"Bonaire, Sint Eustatius and Saba", 740 BA:"Bosnia and Herzegovina", 741 BW:"Botswana", 742 BV:"Bouvet Island", 743 BR:"Brazil", 744 IO:"British Indian Ocean Territory", 745 BN:"Brunei Darussalam", 746 BG:"Bulgaria", 747 BF:"Burkina Faso", 748 BI:"Burundi", 749 KH:"Cambodia", 750 CM:"Cameroon", 751 CA:"Canada", 752 CV:"Cape Verde", 753 KY:"Cayman Islands", 754 CF:"Central African Republic", 755 TD:"Chad", 756 CL:"Chile", 757 CN:"China", 758 CX:"Christmas Island", 759 CC:"Cocos (Keeling) Islands", 760 CO:"Colombia", 761 KM:"Comoros", 762 CG:"Congo", 763 CD:"Congo, the Democratic Republic of the", 764 CK:"Cook Islands", 765 CR:"Costa Rica", 766 CI:"Cote d'Ivoire", 767 HR:"Croatia", 768 CU:"Cuba", 769 CW:"Curacao", 770 CY:"Cyprus", 771 CZ:"Czech Republic", 772 DK:"Denmark", 773 DJ:"Djibouti", 774 DM:"Dominica", 775 DO:"Dominican Republic", 776 EC:"Ecuador", 777 EG:"Egypt", 778 SV:"El Salvador", 779 GQ:"Equatorial Guinea", 780 ER:"Eritrea", 781 EE:"Estonia", 782 ET:"Ethiopia", 783 FK:"Falkland Islands (Malvinas)", 784 FO:"Faroe Islands", 785 FJ:"Fiji", 786 FI:"Finland", 787 FR:"France", 788 GF:"French Guiana", 789 PF:"French Polynesia", 790 TF:"French Southern Territories", 791 GA:"Gabon", 792 GM:"Gambia", 793 GE:"Georgia", 794 DE:"Germany", 795 GH:"Ghana", 796 GI:"Gibraltar", 797 GR:"Greece", 798 GL:"Greenland", 799 GD:"Grenada", 800 GP:"Guadeloupe", 801 GU:"Guam", 802 GT:"Guatemala", 803 GG:"Guernsey", 804 GN:"Guinea", 805 GW:"Guinea-Bissau", 806 GY:"Guyana", 807 HT:"Haiti", 808 HM:"Heard Island and McDonald Islands", 809 VA:"Holy See (Vatican City State)", 810 HN:"Honduras", 811 HK:"Hong Kong", 812 HU:"Hungary", 813 IS:"Iceland", 814 IN:"India", 815 ID:"Indonesia", 816 IR:"Iran, Islamic Republic of", 817 IQ:"Iraq", 818 IE:"Ireland", 819 IM:"Isle of Man", 820 IL:"Israel", 821 IT:"Italy", 822 JM:"Jamaica", 823 JP:"Japan", 824 JE:"Jersey", 825 JO:"Jordan", 826 KZ:"Kazakhstan", 827 KE:"Kenya", 828 KI:"Kiribati", 829 KP:"Korea, Democratic People's Republic of", 830 KR:"Korea, Republic of", 831 KW:"Kuwait", 832 KG:"Kyrgyzstan", 833 LA:"Lao People's Democratic Republic", 834 LV:"Latvia", 835 LB:"Lebanon", 836 LS:"Lesotho", 837 LR:"Liberia", 838 LY:"Libya", 839 LI:"Liechtenstein", 840 LT:"Lithuania", 841 LU:"Luxembourg", 842 MO:"Macao", 843 MK:"Macedonia, the Former Yugoslav Republic of", 844 MG:"Madagascar", 845 MW:"Malawi", 846 MY:"Malaysia", 847 MV:"Maldives", 848 ML:"Mali", 849 MT:"Malta", 850 MH:"Marshall Islands", 851 MQ:"Martinique", 852 MR:"Mauritania", 853 MU:"Mauritius", 854 YT:"Mayotte", 855 MX:"Mexico", 856 FM:"Micronesia, Federated States of", 857 MD:"Moldova, Republic of", 858 MC:"Monaco", 859 MN:"Mongolia", 860 ME:"Montenegro", 861 MS:"Montserrat", 862 MA:"Morocco", 863 MZ:"Mozambique", 864 MM:"Myanmar", 865 NA:"Namibia", 866 NR:"Nauru", 867 NP:"Nepal", 868 NL:"Netherlands", 869 NC:"New Caledonia", 870 NZ:"New Zealand", 871 NI:"Nicaragua", 872 NE:"Niger", 873 NG:"Nigeria", 874 NU:"Niue", 875 NF:"Norfolk Island", 876 MP:"Northern Mariana Islands", 877 NO:"Norway", 878 OM:"Oman", 879 PK:"Pakistan", 880 PW:"Palau", 881 PS:"Palestine, State of", 882 PA:"Panama", 883 PG:"Papua New Guinea", 884 PY:"Paraguay", 885 PE:"Peru", 886 PH:"Philippines", 887 PN:"Pitcairn", 888 PL:"Poland", 889 PT:"Portugal", 890 PR:"Puerto Rico", 891 QA:"Qatar", 892 RE:"Reunion", 893 RO:"Romania", 894 RU:"Russian Federation", 895 RW:"Rwanda", 896 BL:"Saint Bartholemy", 897 SH:"Saint Helena, Ascension and Tristan da Cunha", 898 KN:"Saint Kitts and Nevis", 899 LC:"Saint Lucia", 900 MF:"Saint Martin (French part)", 901 PM:"Saint Pierre and Miquelon", 902 VC:"Saint Vincent and the Grenadines", 903 WS:"Samoa", 904 SM:"San Marino", 905 ST:"Sao Tome and Principe", 906 SA:"Saudi Arabia", 907 SN:"Senegal", 908 RS:"Serbia", 909 SC:"Seychelles", 910 SL:"Sierra Leone", 911 SG:"Singapore", 912 SX:"Sint Maarten (Dutch part)", 913 SK:"Slovakia", 914 SI:"Slovenia", 915 SB:"Solomon Islands", 916 SO:"Somalia", 917 ZA:"South Africa", 918 GS:"South Georgia and the South Sandwich Islands", 919 SS:"South Sudan", 920 ES:"Spain", 921 LK:"Sri Lanka", 922 SD:"Sudan", 923 SR:"Suriname", 924 SJ:"Svalbard and Jan Mayen", 925 SZ:"Swaziland", 926 SE:"Sweden", 927 CH:"Switzerland", 928 SY:"Syrian Arab Republic", 929 TW:"Taiwan, Province of China", 930 TJ:"Tajikistan", 931 TZ:"Tanzania, United Republic of", 932 TH:"Thailand", 933 TL:"Timor-Leste", 934 TG:"Togo", 935 TK:"Tokelau", 936 TO:"Tonga", 937 TT:"Trinidad and Tobago", 938 TN:"Tunisia", 939 TR:"Turkey", 940 TM:"Turkmenistan", 941 TC:"Turks and Caicos Islands", 942 TV:"Tuvalu", 943 UG:"Uganda", 944 UA:"Ukraine", 945 AE:"United Arab Emirates", 946 GB:"United Kingdom", 947 US:"United States", 948 UM:"United States Minor Outlying Islands", 949 UY:"Uruguay", 950 UZ:"Uzbekistan", 951 VU:"Vanuatu", 952 VE:"Venezuela, Bolivarian Republic of", 953 VN:"Viet Nam", 954 VG:"Virgin Islands, British", 955 VI:"Virgin Islands, U.S.", 956 WF:"Wallis and Futuna", 957 EH:"Western Sahara", 958 YE:"Yemen", 959 ZM:"Zambia", 960 ZW:"Zimbabwe" 961 }; 962 963 964 965 /** 966 * Extract subject from certificate as ASN1 object 967 * 968 * @param {X509} cert the certificate 969 * @type ASN1 970 * @return the subject as ASN1 971 */ 972 PKIXCommon.getSubjectAsASN1 = function(cert) { 973 var a = new ASN1(cert.getBytes()); 974 return a.get(0).get(5); 975 } 976 977 978 979 /** 980 * Extract issuer from certificate as ASN1 object 981 * 982 * @param {X509} cert the certificate 983 * @type ASN1 984 * @return the issuer as ASN1 985 */ 986 PKIXCommon.getIssuerAsASN1 = function(cert) { 987 var a = new ASN1(cert.getBytes()); 988 return a.get(0).get(3); 989 } 990 991 992 993 /** 994 * Convert binary data to PEM format 995 * 996 * @param {String} label the label to be used in the MIME header and footer 997 * @param {ByteString} bin the binary data 998 * @type String 999 * @return the MIME/BASE64 encoded string 1000 */ 1001 PKIXCommon.toPEM = function(label, bin) { 1002 assert(typeof(label) == "string", "Parameter label must be string"); 1003 assert(bin instanceof ByteString, "Parameter bin must be ByteString"); 1004 1005 var str = "-----BEGIN " + label + "-----\n"; 1006 1007 var b64 = bin.toString(BASE64); 1008 while(b64.length > 0) { 1009 str += b64.substr(0, 64) + "\n"; 1010 b64 = b64.substr(64); 1011 } 1012 1013 str += "-----END " + label + "-----\n"; 1014 return str; 1015 } 1016 1017 1018 1019 /** 1020 * Parse PEM format and extract binary data 1021 * 1022 * @param {String} label the label of the section 1023 * @param {String} bin the binary data 1024 * @type String 1025 * @return the MIME/BASE64 encoded string 1026 */ 1027 PKIXCommon.parsePEM = function(label, pem) { 1028 assert(typeof(label) == "string", "Parameter label must be string"); 1029 assert(typeof(pem) == "string", "Parameter pem must be string"); 1030 1031 var lines = pem.split("\n"); 1032 1033 var b64str = ""; 1034 var parse = false; 1035 for (var i = 0; i < lines.length; i++) { 1036 var str = lines[i]; 1037 1038 if (str == "-----BEGIN " + label + "-----") { 1039 parse = true; 1040 } else if (str == "-----END " + label + "-----") { 1041 break; 1042 } else if (parse) { 1043 b64str += str; 1044 } 1045 } 1046 1047 return new ByteString(b64str, BASE64); 1048 } 1049 1050 1051 1052 /** 1053 * Writes a byte string object to file 1054 * 1055 * <p>The filename is mapped to the workspace location.</p> 1056 * 1057 * @param {String} filename the fully qualified name of the file 1058 * @param {ByteString} content the content to write 1059 */ 1060 PKIXCommon.writeFileToDisk = function(filename, content) { 1061 var file = new java.io.FileOutputStream(filename); 1062 file.write(content); 1063 file.close(); 1064 } 1065 1066 1067 1068 /** 1069 * Loads a binary file from disk 1070 * 1071 * @param {String} filename the fully qualified file name 1072 * @return the binary content 1073 * @type ByteString 1074 */ 1075 PKIXCommon.readFileFromDisk = function(filename) { 1076 // Open stream 1077 var f = new java.io.FileInputStream(filename); 1078 1079 // Determine file size 1080 var flen = f.available(); 1081 1082 // Allocate native byte array 1083 var bs = java.lang.reflect.Array.newInstance(java.lang.Byte.TYPE, flen); 1084 1085 // Read into byte array 1086 var len = f.read(bs); 1087 1088 f.close(); 1089 1090 // Allocate JavaScript ByteBuffer from native/wrapped byte array 1091 var bb = new ByteBuffer(bs); 1092 1093 // Convert to JavaScript ByteString 1094 var data = bb.toByteString(); 1095 1096 return data; 1097 } 1098 1099 1100 1101 PKIXCommon.test = function() { 1102 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" }; 1103 var dn = PKIXCommon.encodeName(issuer); 1104 print(dn); 1105 1106 var r = PKIXCommon.convertUnsignedInteger(new ByteString("00", HEX)); 1107 assert(r.toString(HEX) == "00"); 1108 var r = PKIXCommon.convertUnsignedInteger(new ByteString("80", HEX)); 1109 assert(r.toString(HEX) == "0080"); 1110 var r = PKIXCommon.convertUnsignedInteger(new ByteString("FF", HEX)); 1111 assert(r.toString(HEX) == "00FF"); 1112 var r = PKIXCommon.convertUnsignedInteger(new ByteString("0000", HEX)); 1113 assert(r.toString(HEX) == "00"); 1114 var r = PKIXCommon.convertUnsignedInteger(new ByteString("0080", HEX)); 1115 assert(r.toString(HEX) == "0080"); 1116 var r = PKIXCommon.convertUnsignedInteger(new ByteString("000080", HEX)); 1117 assert(r.toString(HEX) == "0080"); 1118 } 1119