1 /* asn1cms-1.0.5.js (c) 2013-2017 Kenji Urushima | kjur.github.io/jsrsasign/license 2 */ 3 /* 4 * asn1cms.js - ASN.1 DER encoder and verifier classes for Cryptographic Message Syntax(CMS) 5 * 6 * Copyright (c) 2013-2017 Kenji Urushima (kenji.urushima@gmail.com) 7 * 8 * This software is licensed under the terms of the MIT License. 9 * https://kjur.github.io/jsrsasign/license 10 * 11 * The above copyright and license notice shall be 12 * included in all copies or substantial portions of the Software. 13 */ 14 15 /** 16 * @fileOverview 17 * @name asn1cms-1.0.js 18 * @author Kenji Urushima kenji.urushima@gmail.com 19 * @version 1.0.5 (2017-Sep-15) 20 * @since jsrsasign 4.2.4 21 * @license <a href="https://kjur.github.io/jsrsasign/license/">MIT License</a> 22 */ 23 24 /** 25 * kjur's class library name space 26 * // already documented in asn1-1.0.js 27 * @name KJUR 28 * @namespace kjur's class library name space 29 */ 30 if (typeof KJUR == "undefined" || !KJUR) KJUR = {}; 31 32 /** 33 * kjur's ASN.1 class library name space 34 * // already documented in asn1-1.0.js 35 * @name KJUR.asn1 36 * @namespace 37 */ 38 if (typeof KJUR.asn1 == "undefined" || !KJUR.asn1) KJUR.asn1 = {}; 39 40 /** 41 * kjur's ASN.1 class for Cryptographic Message Syntax(CMS) 42 * <p> 43 * This name space provides 44 * <a href="https://tools.ietf.org/html/rfc5652">RFC 5652 45 * Cryptographic Message Syntax (CMS)</a> SignedData generator. 46 * 47 * <h4>FEATURES</h4> 48 * <ul> 49 * <li>easily generate CMS SignedData</li> 50 * <li>easily verify CMS SignedData</li> 51 * <li>APIs are very similar to BouncyCastle library ASN.1 classes. So easy to learn.</li> 52 * </ul> 53 * 54 * <h4>PROVIDED CLASSES</h4> 55 * <ul> 56 * <li>{@link KJUR.asn1.cms.SignedData}</li> 57 * <li>{@link KJUR.asn1.cms.SignerInfo}</li> 58 * <li>{@link KJUR.asn1.cms.AttributeList}</li> 59 * <li>{@link KJUR.asn1.cms.ContentInfo}</li> 60 * <li>{@link KJUR.asn1.cms.EncapsulatedContentInfo}</li> 61 * <li>{@link KJUR.asn1.cms.IssuerAndSerialNumber}</li> 62 * <li>{@link KJUR.asn1.cms.CMSUtil}</li> 63 * <li>{@link KJUR.asn1.cms.Attribute}</li> 64 * <li>{@link KJUR.asn1.cms.ContentType}</li> 65 * <li>{@link KJUR.asn1.cms.MessageDigest}</li> 66 * <li>{@link KJUR.asn1.cms.SigningTime}</li> 67 * <li>{@link KJUR.asn1.cms.SigningCertificate}</li> 68 * <li>{@link KJUR.asn1.cms.SigningCertificateV2}</li> 69 * </ul> 70 * NOTE: Please ignore method summary and document of this namespace. 71 * This caused by a bug of jsdoc2. 72 * </p> 73 * @name KJUR.asn1.cms 74 * @namespace 75 */ 76 if (typeof KJUR.asn1.cms == "undefined" || !KJUR.asn1.cms) KJUR.asn1.cms = {}; 77 78 /** 79 * Attribute class for base of CMS attribute 80 * @name KJUR.asn1.cms.Attribute 81 * @class Attribute class for base of CMS attribute 82 * @param {Array} params associative array of parameters 83 * @extends KJUR.asn1.ASN1Object 84 * @since jsrsasign 4.2.4 asn1cms 1.0.0 85 * @description 86 * <pre> 87 * Attributes ::= SET OF Attribute 88 * Attribute ::= SEQUENCE { 89 * type OBJECT IDENTIFIER, 90 * values AttributeSetValue } 91 * AttributeSetValue ::= SET OF ANY 92 * </pre> 93 */ 94 KJUR.asn1.cms.Attribute = function(params) { 95 var valueList = [], // array of values 96 _KJUR = KJUR, 97 _KJUR_asn1 = _KJUR.asn1; 98 99 _KJUR_asn1.cms.Attribute.superclass.constructor.call(this); 100 101 this.getEncodedHex = function() { 102 var attrTypeASN1, attrValueASN1, seq; 103 attrTypeASN1 = new _KJUR_asn1.DERObjectIdentifier({"oid": this.attrTypeOid}); 104 105 attrValueASN1 = new _KJUR_asn1.DERSet({"array": this.valueList}); 106 try { 107 attrValueASN1.getEncodedHex(); 108 } catch (ex) { 109 throw "fail valueSet.getEncodedHex in Attribute(1)/" + ex; 110 } 111 112 seq = new _KJUR_asn1.DERSequence({"array": [attrTypeASN1, attrValueASN1]}); 113 try { 114 this.hTLV = seq.getEncodedHex(); 115 } catch (ex) { 116 throw "failed seq.getEncodedHex in Attribute(2)/" + ex; 117 } 118 119 return this.hTLV; 120 }; 121 }; 122 YAHOO.lang.extend(KJUR.asn1.cms.Attribute, KJUR.asn1.ASN1Object); 123 124 /** 125 * class for CMS ContentType attribute 126 * @name KJUR.asn1.cms.ContentType 127 * @class class for CMS ContentType attribute 128 * @param {Array} params associative array of parameters 129 * @extends KJUR.asn1.cms.Attribute 130 * @since jsrsasign 4.2.4 asn1cms 1.0.0 131 * @description 132 * <pre> 133 * Attribute ::= SEQUENCE { 134 * type OBJECT IDENTIFIER, 135 * values AttributeSetValue } 136 * AttributeSetValue ::= SET OF ANY 137 * ContentType ::= OBJECT IDENTIFIER 138 * </pre> 139 * @example 140 * o = new KJUR.asn1.cms.ContentType({name: 'data'}); 141 * o = new KJUR.asn1.cms.ContentType({oid: '1.2.840.113549.1.9.16.1.4'}); 142 */ 143 KJUR.asn1.cms.ContentType = function(params) { 144 var _KJUR = KJUR, 145 _KJUR_asn1 = _KJUR.asn1; 146 147 _KJUR_asn1.cms.ContentType.superclass.constructor.call(this); 148 149 this.attrTypeOid = "1.2.840.113549.1.9.3"; 150 var contentTypeASN1 = null; 151 152 if (typeof params != "undefined") { 153 var contentTypeASN1 = new _KJUR_asn1.DERObjectIdentifier(params); 154 this.valueList = [contentTypeASN1]; 155 } 156 }; 157 YAHOO.lang.extend(KJUR.asn1.cms.ContentType, KJUR.asn1.cms.Attribute); 158 159 /** 160 * class for CMS MessageDigest attribute 161 * @name KJUR.asn1.cms.MessageDigest 162 * @class class for CMS MessageDigest attribute 163 * @param {Array} params associative array of parameters 164 * @extends KJUR.asn1.cms.Attribute 165 * @since jsrsasign 4.2.4 asn1cms 1.0.0 166 * @description 167 * <pre> 168 * Attribute ::= SEQUENCE { 169 * type OBJECT IDENTIFIER, 170 * values AttributeSetValue } 171 * AttributeSetValue ::= SET OF ANY 172 * MessageDigest ::= OCTET STRING 173 * </pre> 174 * @example 175 * o = new KJUR.asn1.cms.MessageDigest({hex: 'a1a2a3a4...'}); 176 */ 177 KJUR.asn1.cms.MessageDigest = function(params) { 178 var _KJUR = KJUR, 179 _KJUR_asn1 = _KJUR.asn1, 180 _DEROctetString = _KJUR_asn1.DEROctetString, 181 _KJUR_asn1_cms = _KJUR_asn1.cms; 182 183 _KJUR_asn1_cms.MessageDigest.superclass.constructor.call(this); 184 this.attrTypeOid = "1.2.840.113549.1.9.4"; 185 186 if (params !== undefined) { 187 if (params.eciObj instanceof _KJUR_asn1_cms.EncapsulatedContentInfo && 188 typeof params.hashAlg === "string") { 189 var dataHex = params.eciObj.eContentValueHex; 190 var hashAlg = params.hashAlg; 191 var hashValueHex = _KJUR.crypto.Util.hashHex(dataHex, hashAlg); 192 var dAttrValue1 = new _DEROctetString({hex: hashValueHex}); 193 dAttrValue1.getEncodedHex(); 194 this.valueList = [dAttrValue1]; 195 } else { 196 var dAttrValue1 = new _DEROctetString(params); 197 dAttrValue1.getEncodedHex(); 198 this.valueList = [dAttrValue1]; 199 } 200 } 201 }; 202 YAHOO.lang.extend(KJUR.asn1.cms.MessageDigest, KJUR.asn1.cms.Attribute); 203 204 /** 205 * class for CMS SigningTime attribute 206 * @name KJUR.asn1.cms.SigningTime 207 * @class class for CMS SigningTime attribute 208 * @param {Array} params associative array of parameters 209 * @extends KJUR.asn1.cms.Attribute 210 * @since jsrsasign 4.2.4 asn1cms 1.0.0 211 * @description 212 * <pre> 213 * Attribute ::= SEQUENCE { 214 * type OBJECT IDENTIFIER, 215 * values AttributeSetValue } 216 * AttributeSetValue ::= SET OF ANY 217 * SigningTime ::= Time 218 * Time ::= CHOICE { 219 * utcTime UTCTime, 220 * generalTime GeneralizedTime } 221 * </pre> 222 * @example 223 * o = new KJUR.asn1.cms.SigningTime(); // current time UTCTime by default 224 * o = new KJUR.asn1.cms.SigningTime({type: 'gen'}); // current time GeneralizedTime 225 * o = new KJUR.asn1.cms.SigningTime({str: '20140517093800Z'}); // specified GeneralizedTime 226 * o = new KJUR.asn1.cms.SigningTime({str: '140517093800Z'}); // specified UTCTime 227 */ 228 KJUR.asn1.cms.SigningTime = function(params) { 229 var _KJUR = KJUR, 230 _KJUR_asn1 = _KJUR.asn1; 231 232 _KJUR_asn1.cms.SigningTime.superclass.constructor.call(this); 233 this.attrTypeOid = "1.2.840.113549.1.9.5"; 234 235 if (params !== undefined) { 236 var asn1 = new _KJUR_asn1.x509.Time(params); 237 try { 238 asn1.getEncodedHex(); 239 } catch (ex) { 240 throw "SigningTime.getEncodedHex() failed/" + ex; 241 } 242 this.valueList = [asn1]; 243 } 244 }; 245 YAHOO.lang.extend(KJUR.asn1.cms.SigningTime, KJUR.asn1.cms.Attribute); 246 247 /** 248 * class for CMS SigningCertificate attribute 249 * @name KJUR.asn1.cms.SigningCertificate 250 * @class class for CMS SigningCertificate attribute 251 * @param {Array} params associative array of parameters 252 * @extends KJUR.asn1.cms.Attribute 253 * @since jsrsasign 4.5.1 asn1cms 1.0.1 254 * @description 255 * <pre> 256 * Attribute ::= SEQUENCE { 257 * type OBJECT IDENTIFIER, 258 * values AttributeSetValue } 259 * AttributeSetValue ::= SET OF ANY 260 * SigningCertificate ::= SEQUENCE { 261 * certs SEQUENCE OF ESSCertID, 262 * policies SEQUENCE OF PolicyInformation OPTIONAL } 263 * ESSCertID ::= SEQUENCE { 264 * certHash Hash, 265 * issuerSerial IssuerSerial OPTIONAL } 266 * IssuerSerial ::= SEQUENCE { 267 * issuer GeneralNames, 268 * serialNumber CertificateSerialNumber } 269 * </pre> 270 * @example 271 * o = new KJUR.asn1.cms.SigningCertificate({array: [certPEM]}); 272 */ 273 KJUR.asn1.cms.SigningCertificate = function(params) { 274 var _KJUR = KJUR, 275 _KJUR_asn1 = _KJUR.asn1, 276 _DERSequence = _KJUR_asn1.DERSequence, 277 _KJUR_asn1_cms = _KJUR_asn1.cms, 278 _KJUR_crypto = _KJUR.crypto; 279 280 _KJUR_asn1_cms.SigningCertificate.superclass.constructor.call(this); 281 this.attrTypeOid = "1.2.840.113549.1.9.16.2.12"; 282 283 this.setCerts = function(listPEM) { 284 var list = []; 285 for (var i = 0; i < listPEM.length; i++) { 286 var hex = pemtohex(listPEM[i]); 287 var certHashHex = _KJUR.crypto.Util.hashHex(hex, 'sha1'); 288 var dCertHash = 289 new _KJUR_asn1.DEROctetString({hex: certHashHex}); 290 dCertHash.getEncodedHex(); 291 var dIssuerSerial = 292 new _KJUR_asn1_cms.IssuerAndSerialNumber({cert: listPEM[i]}); 293 dIssuerSerial.getEncodedHex(); 294 var dESSCertID = 295 new _DERSequence({array: [dCertHash, dIssuerSerial]}); 296 dESSCertID.getEncodedHex(); 297 list.push(dESSCertID); 298 } 299 300 var dValue = new _DERSequence({array: list}); 301 dValue.getEncodedHex(); 302 this.valueList = [dValue]; 303 }; 304 305 if (params !== undefined) { 306 if (typeof params.array == "object") { 307 this.setCerts(params.array); 308 } 309 } 310 }; 311 YAHOO.lang.extend(KJUR.asn1.cms.SigningCertificate, KJUR.asn1.cms.Attribute); 312 313 /** 314 * class for CMS SigningCertificateV2 attribute 315 * @name KJUR.asn1.cms.SigningCertificateV2 316 * @class class for CMS SigningCertificateV2 attribute 317 * @param {Array} params associative array of parameters 318 * @extends KJUR.asn1.cms.Attribute 319 * @since jsrsasign 4.5.1 asn1cms 1.0.1 320 * @description 321 * <pre> 322 * oid-signingCertificateV2 = 1.2.840.113549.1.9.16.2.47 323 * Attribute ::= SEQUENCE { 324 * type OBJECT IDENTIFIER, 325 * values AttributeSetValue } 326 * AttributeSetValue ::= SET OF ANY 327 * SigningCertificateV2 ::= SEQUENCE { 328 * certs SEQUENCE OF ESSCertIDv2, 329 * policies SEQUENCE OF PolicyInformation OPTIONAL } 330 * ESSCertIDv2 ::= SEQUENCE { 331 * hashAlgorithm AlgorithmIdentifier 332 * DEFAULT {algorithm id-sha256}, 333 * certHash Hash, 334 * issuerSerial IssuerSerial OPTIONAL } 335 * Hash ::= OCTET STRING 336 * IssuerSerial ::= SEQUENCE { 337 * issuer GeneralNames, 338 * serialNumber CertificateSerialNumber } 339 * </pre> 340 * @example 341 * // hash algorithm is sha256 by default: 342 * o = new KJUR.asn1.cms.SigningCertificateV2({array: [certPEM]}); 343 * o = new KJUR.asn1.cms.SigningCertificateV2({array: [certPEM], 344 * hashAlg: 'sha512'}); 345 */ 346 KJUR.asn1.cms.SigningCertificateV2 = function(params) { 347 var _KJUR = KJUR, 348 _KJUR_asn1 = _KJUR.asn1, 349 _DERSequence = _KJUR_asn1.DERSequence, 350 _KJUR_asn1_x509 = _KJUR_asn1.x509, 351 _KJUR_asn1_cms = _KJUR_asn1.cms, 352 _KJUR_crypto = _KJUR.crypto; 353 354 _KJUR_asn1_cms.SigningCertificateV2.superclass.constructor.call(this); 355 this.attrTypeOid = "1.2.840.113549.1.9.16.2.47"; 356 357 this.setCerts = function(listPEM, hashAlg) { 358 var list = []; 359 for (var i = 0; i < listPEM.length; i++) { 360 var hex = pemtohex(listPEM[i]); 361 362 var a = []; 363 if (hashAlg !== "sha256") 364 a.push(new _KJUR_asn1_x509.AlgorithmIdentifier({name: hashAlg})); 365 366 var certHashHex = _KJUR_crypto.Util.hashHex(hex, hashAlg); 367 var dCertHash = new _KJUR_asn1.DEROctetString({hex: certHashHex}); 368 dCertHash.getEncodedHex(); 369 a.push(dCertHash); 370 371 var dIssuerSerial = 372 new _KJUR_asn1_cms.IssuerAndSerialNumber({cert: listPEM[i]}); 373 dIssuerSerial.getEncodedHex(); 374 a.push(dIssuerSerial); 375 376 var dESSCertIDv2 = new _DERSequence({array: a}); 377 dESSCertIDv2.getEncodedHex(); 378 list.push(dESSCertIDv2); 379 } 380 381 var dValue = new _DERSequence({array: list}); 382 dValue.getEncodedHex(); 383 this.valueList = [dValue]; 384 }; 385 386 if (params !== undefined) { 387 if (typeof params.array == "object") { 388 var hashAlg = "sha256"; // sha2 default 389 if (typeof params.hashAlg == "string") 390 hashAlg = params.hashAlg; 391 this.setCerts(params.array, hashAlg); 392 } 393 } 394 }; 395 YAHOO.lang.extend(KJUR.asn1.cms.SigningCertificateV2, KJUR.asn1.cms.Attribute); 396 397 /** 398 * class for IssuerAndSerialNumber ASN.1 structure for CMS 399 * @name KJUR.asn1.cms.IssuerAndSerialNumber 400 * @class class for CMS IssuerAndSerialNumber ASN.1 structure for CMS 401 * @param {Array} params associative array of parameters 402 * @extends KJUR.asn1.ASN1Object 403 * @since jsrsasign 4.2.4 asn1cms 1.0.0 404 * @description 405 * <pre> 406 * IssuerAndSerialNumber ::= SEQUENCE { 407 * issuer Name, 408 * serialNumber CertificateSerialNumber } 409 * CertificateSerialNumber ::= INTEGER 410 * </pre> 411 * @example 412 * // specify by X500Name and DERInteger 413 * o = new KJUR.asn1.cms.IssuerAndSerialNumber( 414 * {issuer: {str: '/C=US/O=T1'}, serial {int: 3}}); 415 * // specify by PEM certificate 416 * o = new KJUR.asn1.cms.IssuerAndSerialNumber({cert: certPEM}); 417 * o = new KJUR.asn1.cms.IssuerAndSerialNumber(certPEM); // since 1.0.3 418 */ 419 KJUR.asn1.cms.IssuerAndSerialNumber = function(params) { 420 var _KJUR = KJUR, 421 _KJUR_asn1 = _KJUR.asn1, 422 _DERInteger = _KJUR_asn1.DERInteger, 423 _KJUR_asn1_cms = _KJUR_asn1.cms, 424 _KJUR_asn1_x509 = _KJUR_asn1.x509, 425 _X500Name = _KJUR_asn1_x509.X500Name, 426 _X509 = X509; 427 428 _KJUR_asn1_cms.IssuerAndSerialNumber.superclass.constructor.call(this); 429 var dIssuer = null; 430 var dSerial = null; 431 432 /* 433 * @since asn1cms 1.0.1 434 */ 435 this.setByCertPEM = function(certPEM) { 436 var certHex = pemtohex(certPEM); 437 var x = new _X509(); 438 x.hex = certHex; 439 var issuerTLVHex = x.getIssuerHex(); 440 this.dIssuer = new _X500Name(); 441 this.dIssuer.hTLV = issuerTLVHex; 442 var serialVHex = x.getSerialNumberHex(); 443 this.dSerial = new _DERInteger({hex: serialVHex}); 444 }; 445 446 this.getEncodedHex = function() { 447 var seq = new _KJUR_asn1.DERSequence({"array": [this.dIssuer, 448 this.dSerial]}); 449 this.hTLV = seq.getEncodedHex(); 450 return this.hTLV; 451 }; 452 453 if (params !== undefined) { 454 if (typeof params == "string" && 455 params.indexOf("-----BEGIN ") != -1) { 456 this.setByCertPEM(params); 457 } 458 if (params.issuer && params.serial) { 459 if (params.issuer instanceof _X500Name) { 460 this.dIssuer = params.issuer; 461 } else { 462 this.dIssuer = new _X500Name(params.issuer); 463 } 464 if (params.serial instanceof _DERInteger) { 465 this.dSerial = params.serial; 466 } else { 467 this.dSerial = new _DERInteger(params.serial); 468 } 469 } 470 if (typeof params.cert == "string") { 471 this.setByCertPEM(params.cert); 472 } 473 } 474 }; 475 YAHOO.lang.extend(KJUR.asn1.cms.IssuerAndSerialNumber, KJUR.asn1.ASN1Object); 476 477 /** 478 * class for Attributes ASN.1 structure for CMS 479 * @name KJUR.asn1.cms.AttributeList 480 * @class class for Attributes ASN.1 structure for CMS 481 * @param {Array} params associative array of parameters 482 * @extends KJUR.asn1.ASN1Object 483 * @since jsrsasign 4.2.4 asn1cms 1.0.0 484 * @description 485 * <pre> 486 * Attributes ::= SET OF Attribute 487 * Attribute ::= SEQUENCE { 488 * type OBJECT IDENTIFIER, 489 * values AttributeSetValue } 490 * </pre> 491 * @example 492 * // specify by X500Name and DERInteger 493 * o = new KJUR.asn1.cms.AttributeList({sorted: false}); // ASN.1 BER unsorted SET OF 494 * o = new KJUR.asn1.cms.AttributeList(); // ASN.1 DER sorted by default 495 * o.clear(); // clear list of Attributes 496 * n = o.length(); // get number of Attribute 497 * o.add(new KJUR.asn1.cms.SigningTime()); // add SigningTime attribute 498 * hex = o.getEncodedHex(); // get hex encoded ASN.1 data 499 */ 500 KJUR.asn1.cms.AttributeList = function(params) { 501 var _KJUR = KJUR, 502 _KJUR_asn1 = _KJUR.asn1, 503 _KJUR_asn1_cms = _KJUR_asn1.cms; 504 505 _KJUR_asn1_cms.AttributeList.superclass.constructor.call(this); 506 this.list = new Array(); 507 this.sortFlag = true; 508 509 this.add = function(item) { 510 if (item instanceof _KJUR_asn1_cms.Attribute) { 511 this.list.push(item); 512 } 513 }; 514 515 this.length = function() { 516 return this.list.length; 517 }; 518 519 this.clear = function() { 520 this.list = new Array(); 521 this.hTLV = null; 522 this.hV = null; 523 }; 524 525 this.getEncodedHex = function() { 526 if (typeof this.hTLV == "string") return this.hTLV; 527 var set = new _KJUR_asn1.DERSet({array: this.list, 528 sortflag: this.sortFlag}); 529 this.hTLV = set.getEncodedHex(); 530 return this.hTLV; 531 }; 532 533 if (params !== undefined) { 534 if (typeof params.sortflag != "undefined" && 535 params.sortflag == false) 536 this.sortFlag = false; 537 } 538 }; 539 YAHOO.lang.extend(KJUR.asn1.cms.AttributeList, KJUR.asn1.ASN1Object); 540 541 /** 542 * class for SignerInfo ASN.1 structure of CMS SignedData 543 * @name KJUR.asn1.cms.SignerInfo 544 * @class class for Attributes ASN.1 structure of CMS SigndData 545 * @param {Array} params associative array of parameters 546 * @extends KJUR.asn1.ASN1Object 547 * @since jsrsasign 4.2.4 asn1cms 1.0.0 548 * @description 549 * <pre> 550 * SignerInfo ::= SEQUENCE { 551 * version CMSVersion, 552 * sid SignerIdentifier, 553 * digestAlgorithm DigestAlgorithmIdentifier, 554 * signedAttrs [0] IMPLICIT SignedAttributes OPTIONAL, 555 * signatureAlgorithm SignatureAlgorithmIdentifier, 556 * signature SignatureValue, 557 * unsignedAttrs [1] IMPLICIT UnsignedAttributes OPTIONAL } 558 * </pre> 559 * @example 560 * o = new KJUR.asn1.cms.SignerInfo(); 561 * o.setSignerIdentifier(certPEMstring); 562 * o.dSignedAttrs.add(new KJUR.asn1.cms.ContentType({name: 'data'})); 563 * o.dSignedAttrs.add(new KJUR.asn1.cms.MessageDigest({hex: 'a1b2...'})); 564 * o.dSignedAttrs.add(new KJUR.asn1.cms.SigningTime()); 565 * o.sign(privteKeyParam, "SHA1withRSA"); 566 */ 567 KJUR.asn1.cms.SignerInfo = function(params) { 568 var _KJUR = KJUR, 569 _KJUR_asn1 = _KJUR.asn1, 570 _DERTaggedObject = _KJUR_asn1.DERTaggedObject, 571 _KJUR_asn1_cms = _KJUR_asn1.cms, 572 _AttributeList = _KJUR_asn1_cms.AttributeList, 573 _ContentType = _KJUR_asn1_cms.ContentType, 574 _EncapsulatedContentInfo = _KJUR_asn1_cms.EncapsulatedContentInfo, 575 _MessageDigest = _KJUR_asn1_cms.MessageDigest, 576 _SignedData = _KJUR_asn1_cms.SignedData, 577 _KJUR_asn1_x509 = _KJUR_asn1.x509, 578 _AlgorithmIdentifier = _KJUR_asn1_x509.AlgorithmIdentifier, 579 _KJUR_crypto = _KJUR.crypto, 580 _KEYUTIL = KEYUTIL; 581 582 _KJUR_asn1_cms.SignerInfo.superclass.constructor.call(this); 583 584 this.dCMSVersion = new _KJUR_asn1.DERInteger({'int': 1}); 585 this.dSignerIdentifier = null; 586 this.dDigestAlgorithm = null; 587 this.dSignedAttrs = new _AttributeList(); 588 this.dSigAlg = null; 589 this.dSig = null; 590 this.dUnsignedAttrs = new _AttributeList(); 591 592 this.setSignerIdentifier = function(params) { 593 if (typeof params == "string" && 594 params.indexOf("CERTIFICATE") != -1 && 595 params.indexOf("BEGIN") != -1 && 596 params.indexOf("END") != -1) { 597 598 var certPEM = params; 599 this.dSignerIdentifier = 600 new _KJUR_asn1_cms.IssuerAndSerialNumber({cert: params}); 601 } 602 }; 603 604 /** 605 * set ContentType/MessageDigest/DigestAlgorithms for SignerInfo/SignedData 606 * @name setForContentAndHash 607 * @memberOf KJUR.asn1.cms.SignerInfo 608 * @param {Array} params JSON parameter to set content related field 609 * @description 610 * This method will specify following fields by a parameters: 611 * <ul> 612 * <li>add ContentType signed attribute by encapContentInfo</li> 613 * <li>add MessageDigest signed attribute by encapContentInfo and hashAlg</li> 614 * <li>add a hash algorithm used in MessageDigest to digestAlgorithms field of SignedData</li> 615 * <li>set a hash algorithm used in MessageDigest to digestAlgorithm field of SignerInfo</li> 616 * </ul> 617 * Argument 'params' is an associative array having following elements: 618 * <ul> 619 * <li>eciObj - {@link KJUR.asn1.cms.EncapsulatedContentInfo} object</li> 620 * <li>sdObj - {@link KJUR.asn1.cms.SignedData} object (Option) to set DigestAlgorithms</li> 621 * <li>hashAlg - string of hash algorithm name which is used for MessageDigest attribute</li> 622 * </ul> 623 * some of elements can be omited. 624 * @example 625 * sd = new KJUR.asn1.cms.SignedData(); 626 * signerInfo.setForContentAndHash({sdObj: sd, 627 * eciObj: sd.dEncapContentInfo, 628 * hashAlg: 'sha256'}); 629 */ 630 this.setForContentAndHash = function(params) { 631 if (params !== undefined) { 632 if (params.eciObj instanceof _EncapsulatedContentInfo) { 633 this.dSignedAttrs.add(new _ContentType({oid: '1.2.840.113549.1.7.1'})); 634 this.dSignedAttrs.add(new _MessageDigest({eciObj: params.eciObj, 635 hashAlg: params.hashAlg})); 636 } 637 if (params.sdObj !== undefined && 638 params.sdObj instanceof _SignedData) { 639 if (params.sdObj.digestAlgNameList.join(":").indexOf(params.hashAlg) == -1) { 640 params.sdObj.digestAlgNameList.push(params.hashAlg); 641 } 642 } 643 if (typeof params.hashAlg == "string") { 644 this.dDigestAlgorithm = new _AlgorithmIdentifier({name: params.hashAlg}); 645 } 646 } 647 }; 648 649 this.sign = function(keyParam, sigAlg) { 650 // set algorithm 651 this.dSigAlg = new _AlgorithmIdentifier({name: sigAlg}); 652 653 // set signature 654 var data = this.dSignedAttrs.getEncodedHex(); 655 var prvKey = _KEYUTIL.getKey(keyParam); 656 var sig = new _KJUR_crypto.Signature({alg: sigAlg}); 657 sig.init(prvKey); 658 sig.updateHex(data); 659 var sigValHex = sig.sign(); 660 this.dSig = new _KJUR_asn1.DEROctetString({hex: sigValHex}); 661 }; 662 663 /* 664 * @since asn1cms 1.0.3 665 */ 666 this.addUnsigned = function(attr) { 667 this.hTLV = null; 668 this.dUnsignedAttrs.hTLV = null; 669 this.dUnsignedAttrs.add(attr); 670 }; 671 672 this.getEncodedHex = function() { 673 //alert("sattrs.hTLV=" + this.dSignedAttrs.hTLV); 674 if (this.dSignedAttrs instanceof _AttributeList && 675 this.dSignedAttrs.length() == 0) { 676 throw "SignedAttrs length = 0 (empty)"; 677 } 678 var sa = new _DERTaggedObject({obj: this.dSignedAttrs, 679 tag: 'a0', explicit: false}); 680 var ua = null;; 681 if (this.dUnsignedAttrs.length() > 0) { 682 ua = new _DERTaggedObject({obj: this.dUnsignedAttrs, 683 tag: 'a1', explicit: false}); 684 } 685 686 var items = [ 687 this.dCMSVersion, 688 this.dSignerIdentifier, 689 this.dDigestAlgorithm, 690 sa, 691 this.dSigAlg, 692 this.dSig, 693 ]; 694 if (ua != null) items.push(ua); 695 696 var seq = new _KJUR_asn1.DERSequence({array: items}); 697 this.hTLV = seq.getEncodedHex(); 698 return this.hTLV; 699 }; 700 }; 701 YAHOO.lang.extend(KJUR.asn1.cms.SignerInfo, KJUR.asn1.ASN1Object); 702 703 /** 704 * class for EncapsulatedContentInfo ASN.1 structure for CMS 705 * @name KJUR.asn1.cms.EncapsulatedContentInfo 706 * @class class for EncapsulatedContentInfo ASN.1 structure for CMS 707 * @param {Array} params associative array of parameters 708 * @extends KJUR.asn1.ASN1Object 709 * @since jsrsasign 4.2.4 asn1cms 1.0.0 710 * @description 711 * <pre> 712 * EncapsulatedContentInfo ::= SEQUENCE { 713 * eContentType ContentType, 714 * eContent [0] EXPLICIT OCTET STRING OPTIONAL } 715 * ContentType ::= OBJECT IDENTIFIER 716 * </pre> 717 * @example 718 * o = new KJUR.asn1.cms.EncapsulatedContentInfo(); 719 * o.setContentType('1.2.3.4.5'); // specify eContentType by OID 720 * o.setContentType('data'); // specify eContentType by name 721 * o.setContentValueHex('a1a2a4...'); // specify eContent data by hex string 722 * o.setContentValueStr('apple'); // specify eContent data by UTF-8 string 723 * // for detached contents (i.e. data not concluded in eContent) 724 * o.isDetached = true; // false as default 725 */ 726 KJUR.asn1.cms.EncapsulatedContentInfo = function(params) { 727 var _KJUR = KJUR, 728 _KJUR_asn1 = _KJUR.asn1, 729 _DERTaggedObject = _KJUR_asn1.DERTaggedObject, 730 _DERSequence = _KJUR_asn1.DERSequence, 731 _DERObjectIdentifier = _KJUR_asn1.DERObjectIdentifier, 732 _DEROctetString = _KJUR_asn1.DEROctetString, 733 _KJUR_asn1_cms = _KJUR_asn1.cms; 734 735 _KJUR_asn1_cms.EncapsulatedContentInfo.superclass.constructor.call(this); 736 737 this.dEContentType = new _DERObjectIdentifier({name: 'data'}); 738 this.dEContent = null; 739 this.isDetached = false; 740 this.eContentValueHex = null; 741 742 this.setContentType = function(nameOrOid) { 743 if (nameOrOid.match(/^[0-2][.][0-9.]+$/)) { 744 this.dEContentType = new _DERObjectIdentifier({oid: nameOrOid}); 745 } else { 746 this.dEContentType = new _DERObjectIdentifier({name: nameOrOid}); 747 } 748 }; 749 750 this.setContentValue = function(params) { 751 if (params !== undefined) { 752 if (typeof params.hex == "string") { 753 this.eContentValueHex = params.hex; 754 } else if (typeof params.str == "string") { 755 this.eContentValueHex = utf8tohex(params.str); 756 } 757 } 758 }; 759 760 this.setContentValueHex = function(valueHex) { 761 this.eContentValueHex = valueHex; 762 }; 763 764 this.setContentValueStr = function(valueStr) { 765 this.eContentValueHex = utf8tohex(valueStr); 766 }; 767 768 this.getEncodedHex = function() { 769 if (typeof this.eContentValueHex != "string") { 770 throw "eContentValue not yet set"; 771 } 772 773 var dValue = new _DEROctetString({hex: this.eContentValueHex}); 774 this.dEContent = new _DERTaggedObject({obj: dValue, 775 tag: 'a0', 776 explicit: true}); 777 778 var a = [this.dEContentType]; 779 if (! this.isDetached) a.push(this.dEContent); 780 var seq = new _DERSequence({array: a}); 781 this.hTLV = seq.getEncodedHex(); 782 return this.hTLV; 783 }; 784 }; 785 YAHOO.lang.extend(KJUR.asn1.cms.EncapsulatedContentInfo, KJUR.asn1.ASN1Object); 786 787 // - type 788 // - obj 789 /** 790 * class for ContentInfo ASN.1 structure for CMS 791 * @name KJUR.asn1.cms.ContentInfo 792 * @class class for ContentInfo ASN.1 structure for CMS 793 * @param {Array} params associative array of parameters 794 * @extends KJUR.asn1.ASN1Object 795 * @since jsrsasign 4.2.4 asn1cms 1.0.0 796 * @description 797 * <pre> 798 * ContentInfo ::= SEQUENCE { 799 * contentType ContentType, 800 * content [0] EXPLICIT ANY DEFINED BY contentType } 801 * ContentType ::= OBJECT IDENTIFIER 802 * </pre> 803 * @example 804 * a = [new KJUR.asn1.DERInteger({int: 1}), 805 * new KJUR.asn1.DERInteger({int: 2})]; 806 * seq = new KJUR.asn1.DERSequence({array: a}); 807 * o = new KJUR.asn1.cms.ContentInfo({type: 'data', obj: seq}); 808 */ 809 KJUR.asn1.cms.ContentInfo = function(params) { 810 var _KJUR = KJUR, 811 _KJUR_asn1 = _KJUR.asn1, 812 _DERTaggedObject = _KJUR_asn1.DERTaggedObject, 813 _DERSequence = _KJUR_asn1.DERSequence, 814 _KJUR_asn1_x509 = _KJUR_asn1.x509; 815 816 KJUR.asn1.cms.ContentInfo.superclass.constructor.call(this); 817 818 this.dContentType = null; 819 this.dContent = null; 820 821 this.setContentType = function(params) { 822 if (typeof params == "string") { 823 this.dContentType = _KJUR_asn1_x509.OID.name2obj(params); 824 } 825 }; 826 827 this.getEncodedHex = function() { 828 var dContent0 = new _DERTaggedObject({obj: this.dContent, 829 tag: 'a0', 830 explicit: true}); 831 var seq = new _DERSequence({array: [this.dContentType, dContent0]}); 832 this.hTLV = seq.getEncodedHex(); 833 return this.hTLV; 834 }; 835 836 if (params !== undefined) { 837 if (params.type) 838 this.setContentType(params.type); 839 if (params.obj && 840 params.obj instanceof _KJUR_asn1.ASN1Object) 841 this.dContent = params.obj; 842 } 843 }; 844 YAHOO.lang.extend(KJUR.asn1.cms.ContentInfo, KJUR.asn1.ASN1Object); 845 846 /** 847 * class for SignerInfo ASN.1 structure of CMS SignedData 848 * @name KJUR.asn1.cms.SignedData 849 * @class class for Attributes ASN.1 structure of CMS SigndData 850 * @param {Array} params associative array of parameters 851 * @extends KJUR.asn1.ASN1Object 852 * @since jsrsasign 4.2.4 asn1cms 1.0.0 853 * 854 * @description 855 * <pre> 856 * SignedData ::= SEQUENCE { 857 * version CMSVersion, 858 * digestAlgorithms DigestAlgorithmIdentifiers, 859 * encapContentInfo EncapsulatedContentInfo, 860 * certificates [0] IMPLICIT CertificateSet OPTIONAL, 861 * crls [1] IMPLICIT RevocationInfoChoices OPTIONAL, 862 * signerInfos SignerInfos } 863 * SignerInfos ::= SET OF SignerInfo 864 * CertificateSet ::= SET OF CertificateChoices 865 * DigestAlgorithmIdentifiers ::= SET OF DigestAlgorithmIdentifier 866 * CertificateSet ::= SET OF CertificateChoices 867 * RevocationInfoChoices ::= SET OF RevocationInfoChoice 868 * </pre> 869 * 870 * @example 871 * sd = new KJUR.asn1.cms.SignedData(); 872 * sd.dEncapContentInfo.setContentValueStr("test string"); 873 * sd.signerInfoList[0].setForContentAndHash({sdObj: sd, 874 * eciObj: sd.dEncapContentInfo, 875 * hashAlg: 'sha256'}); 876 * sd.signerInfoList[0].dSignedAttrs.add(new KJUR.asn1.cms.SigningTime()); 877 * sd.signerInfoList[0].setSignerIdentifier(certPEM); 878 * sd.signerInfoList[0].sign(prvP8PEM, "SHA256withRSA"); 879 * hex = sd.getContentInfoEncodedHex(); 880 */ 881 KJUR.asn1.cms.SignedData = function(params) { 882 var _KJUR = KJUR, 883 _KJUR_asn1 = _KJUR.asn1, 884 _ASN1Object = _KJUR_asn1.ASN1Object, 885 _DERInteger = _KJUR_asn1.DERInteger, 886 _DERSet = _KJUR_asn1.DERSet, 887 _DERSequence = _KJUR_asn1.DERSequence, 888 _DERTaggedObject = _KJUR_asn1.DERTaggedObject, 889 _KJUR_asn1_cms = _KJUR_asn1.cms, 890 _EncapsulatedContentInfo = _KJUR_asn1_cms.EncapsulatedContentInfo, 891 _SignerInfo = _KJUR_asn1_cms.SignerInfo, 892 _ContentInfo = _KJUR_asn1_cms.ContentInfo, 893 _KJUR_asn1_x509 = _KJUR_asn1.x509, 894 _AlgorithmIdentifier = _KJUR_asn1_x509.AlgorithmIdentifier; 895 896 KJUR.asn1.cms.SignedData.superclass.constructor.call(this); 897 898 this.dCMSVersion = new _DERInteger({'int': 1}); 899 this.dDigestAlgs = null; 900 this.digestAlgNameList = []; 901 this.dEncapContentInfo = new _EncapsulatedContentInfo(); 902 this.dCerts = null; 903 this.certificateList = []; 904 this.crlList = []; 905 this.signerInfoList = [new _SignerInfo()]; 906 907 this.addCertificatesByPEM = function(certPEM) { 908 var hex = pemtohex(certPEM); 909 var o = new _ASN1Object(); 910 o.hTLV = hex; 911 this.certificateList.push(o); 912 }; 913 914 this.getEncodedHex = function() { 915 if (typeof this.hTLV == "string") return this.hTLV; 916 917 if (this.dDigestAlgs == null) { 918 var digestAlgList = []; 919 for (var i = 0; i < this.digestAlgNameList.length; i++) { 920 var name = this.digestAlgNameList[i]; 921 var o = new _AlgorithmIdentifier({name: name}); 922 digestAlgList.push(o); 923 } 924 this.dDigestAlgs = new _DERSet({array: digestAlgList}); 925 } 926 927 var a = [this.dCMSVersion, 928 this.dDigestAlgs, 929 this.dEncapContentInfo]; 930 931 if (this.dCerts == null) { 932 if (this.certificateList.length > 0) { 933 var o1 = new _DERSet({array: this.certificateList}); 934 this.dCerts 935 = new _DERTaggedObject({obj: o1, 936 tag: 'a0', 937 explicit: false}); 938 } 939 } 940 if (this.dCerts != null) a.push(this.dCerts); 941 942 var dSignerInfos = new _DERSet({array: this.signerInfoList}); 943 a.push(dSignerInfos); 944 945 var seq = new _DERSequence({array: a}); 946 this.hTLV = seq.getEncodedHex(); 947 return this.hTLV; 948 }; 949 950 this.getContentInfo = function() { 951 this.getEncodedHex(); 952 var ci = new _ContentInfo({type: 'signed-data', obj: this}); 953 return ci; 954 }; 955 956 this.getContentInfoEncodedHex = function() { 957 var ci = this.getContentInfo(); 958 var ciHex = ci.getEncodedHex(); 959 return ciHex; 960 }; 961 962 this.getPEM = function() { 963 return hextopem(this.getContentInfoEncodedHex(), "CMS"); 964 }; 965 }; 966 YAHOO.lang.extend(KJUR.asn1.cms.SignedData, KJUR.asn1.ASN1Object); 967 968 /** 969 * CMS utiliteis class 970 * @name KJUR.asn1.cms.CMSUtil 971 * @class CMS utilities class 972 */ 973 KJUR.asn1.cms.CMSUtil = new function() { 974 }; 975 976 /** 977 * generate SignedData object specified by JSON parameters 978 * @name newSignedData 979 * @memberOf KJUR.asn1.cms.CMSUtil 980 * @function 981 * @param {Array} param JSON parameter to generate CMS SignedData 982 * @return {KJUR.asn1.cms.SignedData} object just generated 983 * @description 984 * This method provides more easy way to genereate 985 * CMS SignedData ASN.1 structure by JSON data. 986 * @example 987 * var sd = KJUR.asn1.cms.CMSUtil.newSignedData({ 988 * content: {str: "jsrsasign"}, 989 * certs: [certPEM], 990 * signerInfos: [{ 991 * hashAlg: 'sha256', 992 * sAttr: { 993 * SigningTime: {} 994 * SigningCertificateV2: {array: [certPEM]}, 995 * }, 996 * signerCert: certPEM, 997 * sigAlg: 'SHA256withRSA', 998 * signerPrvKey: prvPEM 999 * }] 1000 * }); 1001 */ 1002 KJUR.asn1.cms.CMSUtil.newSignedData = function(param) { 1003 var _KJUR = KJUR, 1004 _KJUR_asn1 = _KJUR.asn1, 1005 _KJUR_asn1_cms = _KJUR_asn1.cms, 1006 _SignerInfo = _KJUR_asn1_cms.SignerInfo, 1007 _SignedData = _KJUR_asn1_cms.SignedData, 1008 _SigningTime = _KJUR_asn1_cms.SigningTime, 1009 _SigningCertificate = _KJUR_asn1_cms.SigningCertificate, 1010 _SigningCertificateV2 = _KJUR_asn1_cms.SigningCertificateV2, 1011 _KJUR_asn1_cades = _KJUR_asn1.cades, 1012 _SignaturePolicyIdentifier = _KJUR_asn1_cades.SignaturePolicyIdentifier; 1013 1014 var sd = new _SignedData(); 1015 1016 sd.dEncapContentInfo.setContentValue(param.content); 1017 1018 if (typeof param.certs == "object") { 1019 for (var i = 0; i < param.certs.length; i++) { 1020 sd.addCertificatesByPEM(param.certs[i]); 1021 } 1022 } 1023 1024 sd.signerInfoList = []; 1025 for (var i = 0; i < param.signerInfos.length; i++) { 1026 var siParam = param.signerInfos[i]; 1027 var si = new _SignerInfo(); 1028 si.setSignerIdentifier(siParam.signerCert); 1029 1030 si.setForContentAndHash({sdObj: sd, 1031 eciObj: sd.dEncapContentInfo, 1032 hashAlg: siParam.hashAlg}); 1033 1034 for (attrName in siParam.sAttr) { 1035 var attrParam = siParam.sAttr[attrName]; 1036 if (attrName == "SigningTime") { 1037 var attr = new _SigningTime(attrParam); 1038 si.dSignedAttrs.add(attr); 1039 } 1040 if (attrName == "SigningCertificate") { 1041 var attr = new _SigningCertificate(attrParam); 1042 si.dSignedAttrs.add(attr); 1043 } 1044 if (attrName == "SigningCertificateV2") { 1045 var attr = new _SigningCertificateV2(attrParam); 1046 si.dSignedAttrs.add(attr); 1047 } 1048 if (attrName == "SignaturePolicyIdentifier") { 1049 var attr = new _SignaturePolicyIdentifier(attrParam); 1050 si.dSignedAttrs.add(attr); 1051 } 1052 } 1053 1054 si.sign(siParam.signerPrvKey, siParam.sigAlg); 1055 sd.signerInfoList.push(si); 1056 } 1057 1058 return sd; 1059 }; 1060 1061 /** 1062 * verify SignedData specified by JSON parameters 1063 * 1064 * @name verifySignedData 1065 * @memberOf KJUR.asn1.cms.CMSUtil 1066 * @function 1067 * @param {Array} param JSON parameter to verify CMS SignedData 1068 * @return {Object} JSON data as the result of validation 1069 * @since jsrsasign 8.0.4 asn1cms 1.0.5 1070 * @description 1071 * This method provides validation for CMS SignedData. 1072 * Following parameters can be applied: 1073 * <ul> 1074 * <li>cms - hexadecimal data of DER CMS SignedData (aka. PKCS#7 or p7s)</li> 1075 * to verify (OPTION)</li> 1076 * </ul> 1077 * @example 1078 * KJUR.asn1.cms.CMSUtil.verifySignedData({ cms: "3082058a..." }) 1079 * → 1080 * { 1081 * isValid: true, 1082 * parse: ... // parsed data 1083 * signerInfos: [ 1084 * { 1085 * } 1086 * ] 1087 * } 1088 */ 1089 KJUR.asn1.cms.CMSUtil.verifySignedData = function(param) { 1090 var _KJUR = KJUR, 1091 _KJUR_asn1 = _KJUR.asn1, 1092 _KJUR_asn1_cms = _KJUR_asn1.cms, 1093 _SignerInfo = _KJUR_asn1_cms.SignerInfo, 1094 _SignedData = _KJUR_asn1_cms.SignedData, 1095 _SigningTime = _KJUR_asn1_cms.SigningTime, 1096 _SigningCertificate = _KJUR_asn1_cms.SigningCertificate, 1097 _SigningCertificateV2 = _KJUR_asn1_cms.SigningCertificateV2, 1098 _KJUR_asn1_cades = _KJUR_asn1.cades, 1099 _SignaturePolicyIdentifier = _KJUR_asn1_cades.SignaturePolicyIdentifier, 1100 _isHex = _KJUR.lang.String.isHex, 1101 _ASN1HEX = ASN1HEX, 1102 _getVbyList = _ASN1HEX.getVbyList, 1103 _getTLVbyList = _ASN1HEX.getTLVbyList, 1104 _getIdxbyList = _ASN1HEX.getIdxbyList, 1105 _getChildIdx = _ASN1HEX.getChildIdx, 1106 _getTLV = _ASN1HEX.getTLV, 1107 _oidname = _ASN1HEX.oidname, 1108 _hashHex = _KJUR.crypto.Util.hashHex; 1109 1110 if (param.cms === undefined && 1111 ! _isHex(param.cms)) { 1112 } 1113 1114 var hCMS = param.cms; 1115 1116 var _findSignerInfos = function(hCMS, result) { 1117 var idx; 1118 for (var i = 3; i < 6; i++) { 1119 idx = _getIdxbyList(hCMS, 0, [1, 0, i]); 1120 if (idx !== undefined) { 1121 var tag = hCMS.substr(idx, 2); 1122 if (tag === "a0") result.certsIdx = idx; 1123 if (tag === "a1") result.revinfosIdx = idx; 1124 if (tag === "31") result.signerinfosIdx = idx; 1125 } 1126 } 1127 }; 1128 1129 var _parseSignerInfos = function(hCMS, result) { 1130 var idxSignerInfos = result.signerinfosIdx; 1131 if (idxSignerInfos === undefined) return; 1132 var idxList = _getChildIdx(hCMS, idxSignerInfos); 1133 result.signerInfoIdxList = idxList; 1134 for (var i = 0; i < idxList.length; i++) { 1135 var idxSI = idxList[i]; 1136 var info = { idx: idxSI }; 1137 _parseSignerInfo(hCMS, info); 1138 result.signerInfos.push(info); 1139 }; 1140 }; 1141 1142 var _parseSignerInfo = function(hCMS, info) { 1143 var idx = info.idx; 1144 1145 // 1. signer identifier 1146 info.signerid_issuer1 = _getTLVbyList(hCMS, idx, [1, 0], "30"); 1147 info.signerid_serial1 = _getVbyList(hCMS, idx, [1, 1], "02"); 1148 1149 // 2. hash alg 1150 info.hashalg = _oidname(_getVbyList(hCMS, idx, [2, 0], "06")); 1151 1152 // 3. [0] singedAtttrs 1153 var idxSignedAttrs = _getIdxbyList(hCMS, idx, [3], "a0"); 1154 info.idxSignedAttrs = idxSignedAttrs; 1155 _parseSignedAttrs(hCMS, info, idxSignedAttrs); 1156 1157 var aIdx = _getChildIdx(hCMS, idx); 1158 var n = aIdx.length; 1159 if (n < 6) throw "malformed SignerInfo"; 1160 1161 info.sigalg = _oidname(_getVbyList(hCMS, idx, [n - 2, 0], "06")); 1162 info.sigval = _getVbyList(hCMS, idx, [n - 1], "04"); 1163 //info.sigval = _getVbyList(hCMS, 0, [1, 0, 4, 0, 5], "04"); 1164 //info.sigval = hCMS; 1165 }; 1166 1167 var _parseSignedAttrs = function(hCMS, info, idx) { 1168 var aIdx = _getChildIdx(hCMS, idx); 1169 info.signedAttrIdxList = aIdx; 1170 for (var i = 0; i < aIdx.length; i++) { 1171 var idxAttr = aIdx[i]; 1172 var hAttrType = _getVbyList(hCMS, idxAttr, [0], "06"); 1173 var v; 1174 1175 if (hAttrType === "2a864886f70d010905") { // siging time 1176 v = hextoutf8(_getVbyList(hCMS, idxAttr, [1, 0])); 1177 info.saSigningTime = v; 1178 } else if (hAttrType === "2a864886f70d010904") { // message digest 1179 v = _getVbyList(hCMS, idxAttr, [1, 0], "04"); 1180 info.saMessageDigest = v; 1181 } 1182 } 1183 }; 1184 1185 var _parseSignedData = function(hCMS, result) { 1186 // check if signedData (1.2.840.113549.1.7.2) type 1187 if (_getVbyList(hCMS, 0, [0], "06") !== "2a864886f70d010702") { 1188 return result; 1189 } 1190 result.cmsType = "signedData"; 1191 1192 // find eContent data 1193 result.econtent = _getVbyList(hCMS, 0, [1, 0, 2, 1, 0]); 1194 1195 // find certificates,revInfos,signerInfos index 1196 _findSignerInfos(hCMS, result); 1197 1198 result.signerInfos = []; 1199 _parseSignerInfos(hCMS, result); 1200 }; 1201 1202 var _verify = function(hCMS, result) { 1203 var aSI = result.parse.signerInfos; 1204 var n = aSI.length; 1205 var isValid = true; 1206 for (var i = 0; i < n; i++) { 1207 var si = aSI[i]; 1208 _verifySignerInfo(hCMS, result, si, i); 1209 if (! si.isValid) 1210 isValid = false; 1211 } 1212 result.isValid = isValid; 1213 }; 1214 1215 /* 1216 * _findCert 1217 * 1218 * @param hCMS {String} hexadecimal string of CMS signed data 1219 * @param result {Object} JSON object of validation result 1220 * @param si {Object} JSON object of signerInfo in the result above 1221 * @param idx {Number} index of signerInfo??? 1222 */ 1223 var _findCert = function(hCMS, result, si, idx) { 1224 var certsIdx = result.parse.certsIdx; 1225 var aCert; 1226 1227 if (result.certs === undefined) { 1228 aCert = []; 1229 result.certkeys = []; 1230 var aIdx = _getChildIdx(hCMS, certsIdx); 1231 for (var i = 0; i < aIdx.length; i++) { 1232 var hCert = _getTLV(hCMS, aIdx[i]); 1233 var x = new X509(); 1234 x.readCertHex(hCert); 1235 aCert[i] = x; 1236 result.certkeys[i] = x.getPublicKey(); 1237 } 1238 result.certs = aCert; 1239 } else { 1240 aCert = result.certs; 1241 } 1242 1243 result.cccc = aCert.length; 1244 result.cccci = aIdx.length; 1245 1246 for (var i = 0; i < aCert.length; i++) { 1247 var issuer2 = x.getIssuerHex(); 1248 var serial2 = x.getSerialNumberHex(); 1249 if (si.signerid_issuer1 === issuer2 && 1250 si.signerid_serial1 === serial2) { 1251 si.certkey_idx = i; 1252 } 1253 } 1254 }; 1255 1256 var _verifySignerInfo = function(hCMS, result, si, idx) { 1257 si.verifyDetail = {}; 1258 1259 var _detail = si.verifyDetail; 1260 1261 var econtent = result.parse.econtent; 1262 1263 // verify MessageDigest signed attribute 1264 var hashalg = si.hashalg; 1265 var saMessageDigest = si.saMessageDigest; 1266 1267 // verify messageDigest 1268 _detail.validMessageDigest = false; 1269 //_detail._econtent = econtent; 1270 //_detail._hashalg = hashalg; 1271 //_detail._saMD = saMessageDigest; 1272 if (_hashHex(econtent, hashalg) === saMessageDigest) 1273 _detail.validMessageDigest = true; 1274 1275 // find signing certificate 1276 _findCert(hCMS, result, si, idx); 1277 //if (si.signerid_cert === undefined) 1278 // throw Error("can't find signer certificate"); 1279 1280 // verify signature value 1281 _detail.validSignatureValue = false; 1282 var sigalg = si.sigalg; 1283 var hSignedAttr = "31" + _getTLV(hCMS, si.idxSignedAttrs).substr(2); 1284 si.signedattrshex = hSignedAttr; 1285 var pubkey = result.certs[si.certkey_idx].getPublicKey(); 1286 var sig = new KJUR.crypto.Signature({alg: sigalg}); 1287 sig.init(pubkey); 1288 sig.updateHex(hSignedAttr); 1289 var isValid = sig.verify(si.sigval); 1290 _detail.validSignatureValue_isValid = isValid; 1291 if (isValid === true) 1292 _detail.validSignatureValue = true; 1293 1294 // verify SignerInfo totally 1295 si.isValid =false; 1296 if (_detail.validMessageDigest && 1297 _detail.validSignatureValue) { 1298 si.isValid = true; 1299 } 1300 }; 1301 1302 var _findSignerCert = function() { 1303 }; 1304 1305 var result = { isValid: false, parse: {} }; 1306 _parseSignedData(hCMS, result.parse); 1307 1308 _verify(hCMS, result); 1309 1310 return result; 1311 }; 1312 1313 1314