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