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