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