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