1 /*! asn1cms-1.0.2.js (c) 2013-2014 Kenji Urushima | kjur.github.com/jsrsasign/license 2 */ 3 /* 4 * asn1cms.js - ASN.1 DER encoder classes for Cryptographic Message Syntax(CMS) 5 * 6 * Copyright (c) 2014 Kenji Urushima (kenji.urushima@gmail.com) 7 * 8 * This software is licensed under the terms of the MIT License. 9 * http://kjur.github.com/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.2 (2014-Jun-07) 20 * @since jsrsasign 4.2.4 21 * @license <a href="http://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>APIs are very similar to BouncyCastle library ASN.1 classes. So easy to learn.</li> 51 * </ul> 52 * 53 * <h4>PROVIDED CLASSES</h4> 54 * <ul> 55 * <li>{@link KJUR.asn1.cms.SignedData}</li> 56 * <li>{@link KJUR.asn1.cms.SignerInfo}</li> 57 * <li>{@link KJUR.asn1.cms.AttributeList}</li> 58 * <li>{@link KJUR.asn1.cms.ContentInfo}</li> 59 * <li>{@link KJUR.asn1.cms.EncapsulatedContentInfo}</li> 60 * <li>{@link KJUR.asn1.cms.IssuerAndSerialNumber}</li> 61 * <li>{@link KJUR.asn1.cms.CMSUtil}</li> 62 * <li>{@link KJUR.asn1.cms.Attribute}</li> 63 * <li>{@link KJUR.asn1.cms.ContentType}</li> 64 * <li>{@link KJUR.asn1.cms.MessageDigest}</li> 65 * <li>{@link KJUR.asn1.cms.SigningTime}</li> 66 * <li>{@link KJUR.asn1.cms.SigningCertificate}</li> 67 * <li>{@link KJUR.asn1.cms.SigningCertificateV2}</li> 68 * </ul> 69 * NOTE: Please ignore method summary and document of this namespace. 70 * This caused by a bug of jsdoc2. 71 * </p> 72 * @name KJUR.asn1.cms 73 * @namespace 74 */ 75 if (typeof KJUR.asn1.cms == "undefined" || !KJUR.asn1.cms) KJUR.asn1.cms = {}; 76 77 /** 78 * Attribute class for base of CMS attribute 79 * @name KJUR.asn1.cms.Attribute 80 * @class Attribute class for base of CMS attribute 81 * @param {Array} params associative array of parameters 82 * @extends KJUR.asn1.ASN1Object 83 * @since jsrsasign 4.2.4 asn1cms 1.0.0 84 * @description 85 * <pre> 86 * Attributes ::= SET OF Attribute 87 * Attribute ::= SEQUENCE { 88 * type OBJECT IDENTIFIER, 89 * values AttributeSetValue } 90 * AttributeSetValue ::= SET OF ANY 91 * </pre> 92 */ 93 KJUR.asn1.cms.Attribute = function(params) { 94 KJUR.asn1.cms.Attribute.superclass.constructor.call(this); 95 var valueList = []; // array of values 96 97 this.getEncodedHex = function() { 98 var attrTypeASN1, attrValueASN1, seq; 99 attrTypeASN1 = new KJUR.asn1.DERObjectIdentifier({"oid": this.attrTypeOid}); 100 101 attrValueASN1 = new KJUR.asn1.DERSet({"array": this.valueList}); 102 try { 103 attrValueASN1.getEncodedHex(); 104 } catch (ex) { 105 throw "fail valueSet.getEncodedHex in Attribute(1)/" + ex; 106 } 107 108 seq = new KJUR.asn1.DERSequence({"array": [attrTypeASN1, attrValueASN1]}); 109 try { 110 this.hTLV = seq.getEncodedHex(); 111 } catch (ex) { 112 throw "failed seq.getEncodedHex in Attribute(2)/" + ex; 113 } 114 115 return this.hTLV; 116 }; 117 }; 118 YAHOO.lang.extend(KJUR.asn1.cms.Attribute, KJUR.asn1.ASN1Object); 119 120 /** 121 * class for CMS ContentType attribute 122 * @name KJUR.asn1.cms.ContentType 123 * @class class for CMS ContentType attribute 124 * @param {Array} params associative array of parameters 125 * @extends KJUR.asn1.cms.Attribute 126 * @since jsrsasign 4.2.4 asn1cms 1.0.0 127 * @description 128 * <pre> 129 * Attribute ::= SEQUENCE { 130 * type OBJECT IDENTIFIER, 131 * values AttributeSetValue } 132 * AttributeSetValue ::= SET OF ANY 133 * ContentType ::= OBJECT IDENTIFIER 134 * </pre> 135 * @example 136 * o = new KJUR.asn1.cms.ContentType({name: 'data'}); 137 * o = new KJUR.asn1.cms.ContentType({oid: '1.2.840.113549.1.9.16.1.4'}); 138 */ 139 KJUR.asn1.cms.ContentType = function(params) { 140 KJUR.asn1.cms.ContentType.superclass.constructor.call(this); 141 this.attrTypeOid = "1.2.840.113549.1.9.3"; 142 var contentTypeASN1 = null; 143 144 if (typeof params != "undefined") { 145 var contentTypeASN1 = new KJUR.asn1.DERObjectIdentifier(params); 146 this.valueList = [contentTypeASN1]; 147 } 148 }; 149 YAHOO.lang.extend(KJUR.asn1.cms.ContentType, KJUR.asn1.cms.Attribute); 150 151 /** 152 * class for CMS MessageDigest attribute 153 * @name KJUR.asn1.cms.MessageDigest 154 * @class class for CMS MessageDigest attribute 155 * @param {Array} params associative array of parameters 156 * @extends KJUR.asn1.cms.Attribute 157 * @since jsrsasign 4.2.4 asn1cms 1.0.0 158 * @description 159 * <pre> 160 * Attribute ::= SEQUENCE { 161 * type OBJECT IDENTIFIER, 162 * values AttributeSetValue } 163 * AttributeSetValue ::= SET OF ANY 164 * MessageDigest ::= OCTET STRING 165 * </pre> 166 * @example 167 * o = new KJUR.asn1.cms.MessageDigest({hex: 'a1a2a3a4...'}); 168 */ 169 KJUR.asn1.cms.MessageDigest = function(params) { 170 KJUR.asn1.cms.MessageDigest.superclass.constructor.call(this); 171 this.attrTypeOid = "1.2.840.113549.1.9.4"; 172 173 if (typeof params != "undefined") { 174 if (params.eciObj instanceof KJUR.asn1.cms.EncapsulatedContentInfo && 175 typeof params.hashAlg == "string") { 176 var dataHex = params.eciObj.eContentValueHex; 177 var hashAlg = params.hashAlg; 178 var hashValueHex = KJUR.crypto.Util.hashHex(dataHex, hashAlg); 179 var dAttrValue1 = new KJUR.asn1.DEROctetString({hex: hashValueHex}); 180 dAttrValue1.getEncodedHex(); 181 this.valueList = [dAttrValue1]; 182 } else { 183 var dAttrValue1 = new KJUR.asn1.DEROctetString(params); 184 dAttrValue1.getEncodedHex(); 185 this.valueList = [dAttrValue1]; 186 } 187 } 188 }; 189 YAHOO.lang.extend(KJUR.asn1.cms.MessageDigest, KJUR.asn1.cms.Attribute); 190 191 /** 192 * class for CMS SigningTime attribute 193 * @name KJUR.asn1.cms.SigningTime 194 * @class class for CMS SigningTime attribute 195 * @param {Array} params associative array of parameters 196 * @extends KJUR.asn1.cms.Attribute 197 * @since jsrsasign 4.2.4 asn1cms 1.0.0 198 * @description 199 * <pre> 200 * Attribute ::= SEQUENCE { 201 * type OBJECT IDENTIFIER, 202 * values AttributeSetValue } 203 * AttributeSetValue ::= SET OF ANY 204 * SigningTime ::= Time 205 * Time ::= CHOICE { 206 * utcTime UTCTime, 207 * generalTime GeneralizedTime } 208 * </pre> 209 * @example 210 * o = new KJUR.asn1.cms.SigningTime(); // current time UTCTime by default 211 * o = new KJUR.asn1.cms.SigningTime({type: 'gen'}); // current time GeneralizedTime 212 * o = new KJUR.asn1.cms.SigningTime({str: '20140517093800Z'}); // specified GeneralizedTime 213 * o = new KJUR.asn1.cms.SigningTime({str: '140517093800Z'}); // specified UTCTime 214 */ 215 KJUR.asn1.cms.SigningTime = function(params) { 216 KJUR.asn1.cms.SigningTime.superclass.constructor.call(this); 217 this.attrTypeOid = "1.2.840.113549.1.9.5"; 218 219 if (typeof params != "undefined") { 220 var asn1 = new KJUR.asn1.x509.Time(params); 221 try { 222 asn1.getEncodedHex(); 223 } catch (ex) { 224 throw "SigningTime.getEncodedHex() failed/" + ex; 225 } 226 this.valueList = [asn1]; 227 } 228 }; 229 YAHOO.lang.extend(KJUR.asn1.cms.SigningTime, KJUR.asn1.cms.Attribute); 230 231 /** 232 * class for CMS SigningCertificate attribute 233 * @name KJUR.asn1.cms.SigningCertificate 234 * @class class for CMS SigningCertificate attribute 235 * @param {Array} params associative array of parameters 236 * @extends KJUR.asn1.cms.Attribute 237 * @since jsrsasign 4.5.1 asn1cms 1.0.1 238 * @description 239 * <pre> 240 * Attribute ::= SEQUENCE { 241 * type OBJECT IDENTIFIER, 242 * values AttributeSetValue } 243 * AttributeSetValue ::= SET OF ANY 244 * SigningCertificate ::= SEQUENCE { 245 * certs SEQUENCE OF ESSCertID, 246 * policies SEQUENCE OF PolicyInformation OPTIONAL } 247 * ESSCertID ::= SEQUENCE { 248 * certHash Hash, 249 * issuerSerial IssuerSerial OPTIONAL } 250 * IssuerSerial ::= SEQUENCE { 251 * issuer GeneralNames, 252 * serialNumber CertificateSerialNumber } 253 * </pre> 254 * @example 255 * o = new KJUR.asn1.cms.SigningCertificate({array: [certPEM]}); 256 */ 257 KJUR.asn1.cms.SigningCertificate = function(params) { 258 KJUR.asn1.cms.SigningCertificate.superclass.constructor.call(this); 259 this.attrTypeOid = "1.2.840.113549.1.9.16.2.12"; 260 var nA = KJUR.asn1; 261 var nC = KJUR.asn1.cms; 262 var nY = KJUR.crypto; 263 264 this.setCerts = function(listPEM) { 265 var list = []; 266 for (var i = 0; i < listPEM.length; i++) { 267 var hex = KEYUTIL.getHexFromPEM(listPEM[i]); 268 var certHashHex = nY.Util.hashHex(hex, 'sha1'); 269 var dCertHash = new nA.DEROctetString({hex: certHashHex}); 270 dCertHash.getEncodedHex(); 271 var dIssuerSerial = 272 new nC.IssuerAndSerialNumber({cert: listPEM[i]}); 273 dIssuerSerial.getEncodedHex(); 274 var dESSCertID = 275 new nA.DERSequence({array: [dCertHash, dIssuerSerial]}); 276 dESSCertID.getEncodedHex(); 277 list.push(dESSCertID); 278 } 279 280 var dValue = new nA.DERSequence({array: list}); 281 dValue.getEncodedHex(); 282 this.valueList = [dValue]; 283 }; 284 285 if (typeof params != "undefined") { 286 if (typeof params.array == "object") { 287 this.setCerts(params.array); 288 } 289 } 290 }; 291 YAHOO.lang.extend(KJUR.asn1.cms.SigningCertificate, KJUR.asn1.cms.Attribute); 292 293 /** 294 * class for CMS SigningCertificateV2 attribute 295 * @name KJUR.asn1.cms.SigningCertificateV2 296 * @class class for CMS SigningCertificateV2 attribute 297 * @param {Array} params associative array of parameters 298 * @extends KJUR.asn1.cms.Attribute 299 * @since jsrsasign 4.5.1 asn1cms 1.0.1 300 * @description 301 * <pre> 302 * oid-signingCertificateV2 = 1.2.840.113549.1.9.16.2.47 303 * Attribute ::= SEQUENCE { 304 * type OBJECT IDENTIFIER, 305 * values AttributeSetValue } 306 * AttributeSetValue ::= SET OF ANY 307 * SigningCertificateV2 ::= SEQUENCE { 308 * certs SEQUENCE OF ESSCertIDv2, 309 * policies SEQUENCE OF PolicyInformation OPTIONAL } 310 * ESSCertIDv2 ::= SEQUENCE { 311 * hashAlgorithm AlgorithmIdentifier 312 * DEFAULT {algorithm id-sha256}, 313 * certHash Hash, 314 * issuerSerial IssuerSerial OPTIONAL } 315 * Hash ::= OCTET STRING 316 * IssuerSerial ::= SEQUENCE { 317 * issuer GeneralNames, 318 * serialNumber CertificateSerialNumber } 319 * </pre> 320 * @example 321 * // hash algorithm is sha256 by default: 322 * o = new KJUR.asn1.cms.SigningCertificateV2({array: [certPEM]}); 323 * o = new KJUR.asn1.cms.SigningCertificateV2({array: [certPEM], 324 * hashAlg: 'sha512'}); 325 */ 326 KJUR.asn1.cms.SigningCertificateV2 = function(params) { 327 KJUR.asn1.cms.SigningCertificateV2.superclass.constructor.call(this); 328 this.attrTypeOid = "1.2.840.113549.1.9.16.2.47"; 329 var nA = KJUR.asn1; 330 var nX = KJUR.asn1.x509; 331 var nC = KJUR.asn1.cms; 332 var nY = KJUR.crypto; 333 334 this.setCerts = function(listPEM, hashAlg) { 335 var list = []; 336 for (var i = 0; i < listPEM.length; i++) { 337 var hex = KEYUTIL.getHexFromPEM(listPEM[i]); 338 339 var a = []; 340 if (hashAlg != "sha256") 341 a.push(new nX.AlgorithmIdentifier({name: hashAlg})); 342 343 var certHashHex = nY.Util.hashHex(hex, hashAlg); 344 var dCertHash = new nA.DEROctetString({hex: certHashHex}); 345 dCertHash.getEncodedHex(); 346 a.push(dCertHash); 347 348 var dIssuerSerial = 349 new nC.IssuerAndSerialNumber({cert: listPEM[i]}); 350 dIssuerSerial.getEncodedHex(); 351 a.push(dIssuerSerial); 352 353 var dESSCertIDv2 = 354 new nA.DERSequence({array: a}); 355 dESSCertIDv2.getEncodedHex(); 356 list.push(dESSCertIDv2); 357 } 358 359 var dValue = new nA.DERSequence({array: list}); 360 dValue.getEncodedHex(); 361 this.valueList = [dValue]; 362 }; 363 364 if (typeof params != "undefined") { 365 if (typeof params.array == "object") { 366 var hashAlg = "sha256"; // sha2 default 367 if (typeof params.hashAlg == "string") 368 hashAlg = params.hashAlg; 369 this.setCerts(params.array, hashAlg); 370 } 371 } 372 }; 373 YAHOO.lang.extend(KJUR.asn1.cms.SigningCertificateV2, KJUR.asn1.cms.Attribute); 374 375 /** 376 * class for IssuerAndSerialNumber ASN.1 structure for CMS 377 * @name KJUR.asn1.cms.IssuerAndSerialNumber 378 * @class class for CMS IssuerAndSerialNumber ASN.1 structure for CMS 379 * @param {Array} params associative array of parameters 380 * @extends KJUR.asn1.ASN1Object 381 * @since jsrsasign 4.2.4 asn1cms 1.0.0 382 * @description 383 * <pre> 384 * IssuerAndSerialNumber ::= SEQUENCE { 385 * issuer Name, 386 * serialNumber CertificateSerialNumber } 387 * CertificateSerialNumber ::= INTEGER 388 * </pre> 389 * @example 390 * // specify by X500Name and DERInteger 391 * o = new KJUR.asn1.cms.IssuerAndSerialNumber( 392 * {issuer: {str: '/C=US/O=T1'}, serial {int: 3}}); 393 * // specify by PEM certificate 394 * o = new KJUR.asn1.cms.IssuerAndSerialNumber({cert: certPEM}); 395 * o = new KJUR.asn1.cms.IssuerAndSerialNumber(certPEM); // since 1.0.3 396 */ 397 KJUR.asn1.cms.IssuerAndSerialNumber = function(params) { 398 KJUR.asn1.cms.IssuerAndSerialNumber.superclass.constructor.call(this); 399 var dIssuer = null; 400 var dSerial = null; 401 var nA = KJUR.asn1; 402 var nX = nA.x509; 403 404 /* 405 * @since asn1cms 1.0.1 406 */ 407 this.setByCertPEM = function(certPEM) { 408 var certHex = KEYUTIL.getHexFromPEM(certPEM); 409 var x = new X509(); 410 x.hex = certHex; 411 var issuerTLVHex = x.getIssuerHex(); 412 this.dIssuer = new nX.X500Name(); 413 this.dIssuer.hTLV = issuerTLVHex; 414 var serialVHex = x.getSerialNumberHex(); 415 this.dSerial = new nA.DERInteger({hex: serialVHex}); 416 }; 417 418 this.getEncodedHex = function() { 419 var seq = new KJUR.asn1.DERSequence({"array": [this.dIssuer, 420 this.dSerial]}); 421 this.hTLV = seq.getEncodedHex(); 422 return this.hTLV; 423 }; 424 425 if (typeof params != "undefined") { 426 if (typeof params == "string" && 427 params.indexOf("-----BEGIN ") != -1) { 428 this.setByCertPEM(params); 429 } 430 if (params.issuer && params.serial) { 431 if (params.issuer instanceof KJUR.asn1.x509.X500Name) { 432 this.dIssuer = params.issuer; 433 } else { 434 this.dIssuer = new KJUR.asn1.x509.X500Name(params.issuer); 435 } 436 if (params.serial instanceof KJUR.asn1.DERInteger) { 437 this.dSerial = params.serial; 438 } else { 439 this.dSerial = new KJUR.asn1.DERInteger(params.serial); 440 } 441 } 442 if (typeof params.cert == "string") { 443 this.setByCertPEM(params.cert); 444 } 445 } 446 }; 447 YAHOO.lang.extend(KJUR.asn1.cms.IssuerAndSerialNumber, KJUR.asn1.ASN1Object); 448 449 /** 450 * class for Attributes ASN.1 structure for CMS 451 * @name KJUR.asn1.cms.AttributeList 452 * @class class for Attributes ASN.1 structure for CMS 453 * @param {Array} params associative array of parameters 454 * @extends KJUR.asn1.ASN1Object 455 * @since jsrsasign 4.2.4 asn1cms 1.0.0 456 * @description 457 * <pre> 458 * Attributes ::= SET OF Attribute 459 * Attribute ::= SEQUENCE { 460 * type OBJECT IDENTIFIER, 461 * values AttributeSetValue } 462 * </pre> 463 * @example 464 * // specify by X500Name and DERInteger 465 * o = new KJUR.asn1.cms.AttributeList({sorted: false}); // ASN.1 BER unsorted SET OF 466 * o = new KJUR.asn1.cms.AttributeList(); // ASN.1 DER sorted by default 467 * o.clear(); // clear list of Attributes 468 * n = o.length(); // get number of Attribute 469 * o.add(new KJUR.asn1.cms.SigningTime()); // add SigningTime attribute 470 * hex = o.getEncodedHex(); // get hex encoded ASN.1 data 471 */ 472 KJUR.asn1.cms.AttributeList = function(params) { 473 KJUR.asn1.cms.AttributeList.superclass.constructor.call(this); 474 this.list = new Array(); 475 this.sortFlag = true; 476 477 this.add = function(item) { 478 if (item instanceof KJUR.asn1.cms.Attribute) { 479 this.list.push(item); 480 } 481 }; 482 483 this.length = function() { 484 return this.list.length; 485 }; 486 487 this.clear = function() { 488 this.list = new Array(); 489 this.hTLV = null; 490 this.hV = null; 491 }; 492 493 this.getEncodedHex = function() { 494 if (typeof this.hTLV == "string") return this.hTLV; 495 var set = new KJUR.asn1.DERSet({array: this.list, 496 sortflag: this.sortFlag}); 497 this.hTLV = set.getEncodedHex(); 498 return this.hTLV; 499 }; 500 501 if (typeof params != "undefined") { 502 if (typeof params.sortflag != "undefined" && 503 params.sortflag == false) 504 this.sortFlag = false; 505 } 506 }; 507 YAHOO.lang.extend(KJUR.asn1.cms.AttributeList, KJUR.asn1.ASN1Object); 508 509 /** 510 * class for SignerInfo ASN.1 structure of CMS SignedData 511 * @name KJUR.asn1.cms.SignerInfo 512 * @class class for Attributes ASN.1 structure of CMS SigndData 513 * @param {Array} params associative array of parameters 514 * @extends KJUR.asn1.ASN1Object 515 * @since jsrsasign 4.2.4 asn1cms 1.0.0 516 * @description 517 * <pre> 518 * SignerInfo ::= SEQUENCE { 519 * version CMSVersion, 520 * sid SignerIdentifier, 521 * digestAlgorithm DigestAlgorithmIdentifier, 522 * signedAttrs [0] IMPLICIT SignedAttributes OPTIONAL, 523 * signatureAlgorithm SignatureAlgorithmIdentifier, 524 * signature SignatureValue, 525 * unsignedAttrs [1] IMPLICIT UnsignedAttributes OPTIONAL } 526 * </pre> 527 * @example 528 * o = new KJUR.asn1.cms.SignerInfo(); 529 * o.setSignerIdentifier(certPEMstring); 530 * o.dSignedAttrs.add(new KJUR.asn1.cms.ContentType({name: 'data'})); 531 * o.dSignedAttrs.add(new KJUR.asn1.cms.MessageDigest({hex: 'a1b2...'})); 532 * o.dSignedAttrs.add(new KJUR.asn1.cms.SigningTime()); 533 * o.sign(privteKeyParam, "SHA1withRSA"); 534 */ 535 KJUR.asn1.cms.SignerInfo = function(params) { 536 KJUR.asn1.cms.SignerInfo.superclass.constructor.call(this); 537 var nA = KJUR.asn1; 538 var nC = KJUR.asn1.cms; 539 var nX = KJUR.asn1.x509; 540 541 this.dCMSVersion = new nA.DERInteger({'int': 1}); 542 this.dSignerIdentifier = null; 543 this.dDigestAlgorithm = null; 544 this.dSignedAttrs = new nC.AttributeList(); 545 this.dSigAlg = null; 546 this.dSig = null; 547 this.dUnsignedAttrs = new nC.AttributeList(); 548 549 this.setSignerIdentifier = function(params) { 550 if (typeof params == "string" && 551 params.indexOf("CERTIFICATE") != -1 && 552 params.indexOf("BEGIN") != -1 && 553 params.indexOf("END") != -1) { 554 555 var certPEM = params; 556 this.dSignerIdentifier = 557 new nC.IssuerAndSerialNumber({cert: params}); 558 } 559 }; 560 561 /** 562 * set ContentType/MessageDigest/DigestAlgorithms for SignerInfo/SignedData 563 * @name setForContentAndHash 564 * @memberOf KJUR.asn1.cms.SignerInfo 565 * @param {Array} params JSON parameter to set content related field 566 * @description 567 * This method will specify following fields by a parameters: 568 * <ul> 569 * <li>add ContentType signed attribute by encapContentInfo</li> 570 * <li>add MessageDigest signed attribute by encapContentInfo and hashAlg</li> 571 * <li>add a hash algorithm used in MessageDigest to digestAlgorithms field of SignedData</li> 572 * <li>set a hash algorithm used in MessageDigest to digestAlgorithm field of SignerInfo</li> 573 * </ul> 574 * Argument 'params' is an associative array having following elements: 575 * <ul> 576 * <li>eciObj - {@link KJUR.asn1.cms.EncapsulatedContentInfo} object</li> 577 * <li>sdObj - {@link KJUR.asn1.cms.SignedData} object (Option) to set DigestAlgorithms</li> 578 * <li>hashAlg - string of hash algorithm name which is used for MessageDigest attribute</li> 579 * </ul> 580 * some of elements can be omited. 581 * @example 582 * sd = new KJUR.asn1.cms.SignedData(); 583 * signerInfo.setForContentAndHash({sdObj: sd, 584 * eciObj: sd.dEncapContentInfo, 585 * hashAlg: 'sha256'}); 586 */ 587 this.setForContentAndHash = function(params) { 588 if (typeof params != "undefined") { 589 if (params.eciObj instanceof KJUR.asn1.cms.EncapsulatedContentInfo) { 590 this.dSignedAttrs.add(new nC.ContentType({oid: '1.2.840.113549.1.7.1'})); 591 this.dSignedAttrs.add(new nC.MessageDigest({eciObj: params.eciObj, 592 hashAlg: params.hashAlg})); 593 } 594 if (typeof params.sdObj != "undefined" && 595 params.sdObj instanceof KJUR.asn1.cms.SignedData) { 596 if (params.sdObj.digestAlgNameList.join(":").indexOf(params.hashAlg) == -1) { 597 params.sdObj.digestAlgNameList.push(params.hashAlg); 598 } 599 } 600 if (typeof params.hashAlg == "string") { 601 this.dDigestAlgorithm = new nX.AlgorithmIdentifier({name: params.hashAlg}); 602 } 603 } 604 }; 605 606 this.sign = function(keyParam, sigAlg) { 607 // set algorithm 608 this.dSigAlg = new nX.AlgorithmIdentifier({name: sigAlg}); 609 610 // set signature 611 var data = this.dSignedAttrs.getEncodedHex(); 612 var prvKey = KEYUTIL.getKey(keyParam); 613 var sig = new KJUR.crypto.Signature({alg: sigAlg}); 614 sig.init(prvKey); 615 sig.updateHex(data); 616 var sigValHex = sig.sign(); 617 this.dSig = new nA.DEROctetString({hex: sigValHex}); 618 }; 619 620 /* 621 * @since asn1cms 1.0.3 622 */ 623 this.addUnsigned = function(attr) { 624 this.hTLV = null; 625 this.dUnsignedAttrs.hTLV = null; 626 this.dUnsignedAttrs.add(attr); 627 }; 628 629 this.getEncodedHex = function() { 630 //alert("sattrs.hTLV=" + this.dSignedAttrs.hTLV); 631 if (this.dSignedAttrs instanceof KJUR.asn1.cms.AttributeList && 632 this.dSignedAttrs.length() == 0) { 633 throw "SignedAttrs length = 0 (empty)"; 634 } 635 var sa = new nA.DERTaggedObject({obj: this.dSignedAttrs, 636 tag: 'a0', explicit: false}); 637 var ua = null;; 638 if (this.dUnsignedAttrs.length() > 0) { 639 ua = new nA.DERTaggedObject({obj: this.dUnsignedAttrs, 640 tag: 'a1', explicit: false}); 641 } 642 643 var items = [ 644 this.dCMSVersion, 645 this.dSignerIdentifier, 646 this.dDigestAlgorithm, 647 sa, 648 this.dSigAlg, 649 this.dSig, 650 ]; 651 if (ua != null) items.push(ua); 652 653 var seq = new nA.DERSequence({array: items}); 654 this.hTLV = seq.getEncodedHex(); 655 return this.hTLV; 656 }; 657 }; 658 YAHOO.lang.extend(KJUR.asn1.cms.SignerInfo, KJUR.asn1.ASN1Object); 659 660 /** 661 * class for EncapsulatedContentInfo ASN.1 structure for CMS 662 * @name KJUR.asn1.cms.EncapsulatedContentInfo 663 * @class class for EncapsulatedContentInfo ASN.1 structure for CMS 664 * @param {Array} params associative array of parameters 665 * @extends KJUR.asn1.ASN1Object 666 * @since jsrsasign 4.2.4 asn1cms 1.0.0 667 * @description 668 * <pre> 669 * EncapsulatedContentInfo ::= SEQUENCE { 670 * eContentType ContentType, 671 * eContent [0] EXPLICIT OCTET STRING OPTIONAL } 672 * ContentType ::= OBJECT IDENTIFIER 673 * </pre> 674 * @example 675 * o = new KJUR.asn1.cms.EncapsulatedContentInfo(); 676 * o.setContentType('1.2.3.4.5'); // specify eContentType by OID 677 * o.setContentType('data'); // specify eContentType by name 678 * o.setContentValueHex('a1a2a4...'); // specify eContent data by hex string 679 * o.setContentValueStr('apple'); // specify eContent data by UTF-8 string 680 * // for detached contents (i.e. data not concluded in eContent) 681 * o.isDetached = true; // false as default 682 */ 683 KJUR.asn1.cms.EncapsulatedContentInfo = function(params) { 684 KJUR.asn1.cms.EncapsulatedContentInfo.superclass.constructor.call(this); 685 var nA = KJUR.asn1; 686 var nC = KJUR.asn1.cms; 687 var nX = KJUR.asn1.x509; 688 this.dEContentType = new nA.DERObjectIdentifier({name: 'data'}); 689 this.dEContent = null; 690 this.isDetached = false; 691 this.eContentValueHex = null; 692 693 this.setContentType = function(nameOrOid) { 694 if (nameOrOid.match(/^[0-2][.][0-9.]+$/)) { 695 this.dEContentType = new nA.DERObjectIdentifier({oid: nameOrOid}); 696 } else { 697 this.dEContentType = new nA.DERObjectIdentifier({name: nameOrOid}); 698 } 699 }; 700 701 this.setContentValue = function(params) { 702 if (typeof params != "undefined") { 703 if (typeof params.hex == "string") { 704 this.eContentValueHex = params.hex; 705 } else if (typeof params.str == "string") { 706 this.eContentValueHex = utf8tohex(params.str); 707 } 708 } 709 }; 710 711 this.setContentValueHex = function(valueHex) { 712 this.eContentValueHex = valueHex; 713 }; 714 715 this.setContentValueStr = function(valueStr) { 716 this.eContentValueHex = utf8tohex(valueStr); 717 }; 718 719 this.getEncodedHex = function() { 720 if (typeof this.eContentValueHex != "string") { 721 throw "eContentValue not yet set"; 722 } 723 724 var dValue = new nA.DEROctetString({hex: this.eContentValueHex}); 725 this.dEContent = new nA.DERTaggedObject({obj: dValue, 726 tag: 'a0', 727 explicit: true}); 728 729 var a = [this.dEContentType]; 730 if (! this.isDetached) a.push(this.dEContent); 731 var seq = new nA.DERSequence({array: a}); 732 this.hTLV = seq.getEncodedHex(); 733 return this.hTLV; 734 }; 735 }; 736 YAHOO.lang.extend(KJUR.asn1.cms.EncapsulatedContentInfo, KJUR.asn1.ASN1Object); 737 738 // - type 739 // - obj 740 /** 741 * class for ContentInfo ASN.1 structure for CMS 742 * @name KJUR.asn1.cms.ContentInfo 743 * @class class for ContentInfo ASN.1 structure for CMS 744 * @param {Array} params associative array of parameters 745 * @extends KJUR.asn1.ASN1Object 746 * @since jsrsasign 4.2.4 asn1cms 1.0.0 747 * @description 748 * <pre> 749 * ContentInfo ::= SEQUENCE { 750 * contentType ContentType, 751 * content [0] EXPLICIT ANY DEFINED BY contentType } 752 * ContentType ::= OBJECT IDENTIFIER 753 * </pre> 754 * @example 755 * a = [new KJUR.asn1.DERInteger({int: 1}), 756 * new KJUR.asn1.DERInteger({int: 2})]; 757 * seq = new KJUR.asn1.DERSequence({array: a}); 758 * o = new KJUR.asn1.cms.ContentInfo({type: 'data', obj: seq}); 759 */ 760 KJUR.asn1.cms.ContentInfo = function(params) { 761 KJUR.asn1.cms.ContentInfo.superclass.constructor.call(this); 762 var nA = KJUR.asn1; 763 var nC = KJUR.asn1.cms; 764 var nX = KJUR.asn1.x509; 765 766 this.dContentType = null; 767 this.dContent = null; 768 769 this.setContentType = function(params) { 770 if (typeof params == "string") { 771 this.dContentType = nX.OID.name2obj(params); 772 } 773 }; 774 775 this.getEncodedHex = function() { 776 var dContent0 = new nA.DERTaggedObject({obj: this.dContent, tag: 'a0', explicit: true}); 777 var seq = new nA.DERSequence({array: [this.dContentType, dContent0]}); 778 this.hTLV = seq.getEncodedHex(); 779 return this.hTLV; 780 }; 781 782 if (typeof params != "undefined") { 783 if (params.type) this.setContentType(params.type); 784 if (params.obj && params.obj instanceof nA.ASN1Object) this.dContent = params.obj; 785 } 786 }; 787 YAHOO.lang.extend(KJUR.asn1.cms.ContentInfo, KJUR.asn1.ASN1Object); 788 789 /** 790 * class for SignerInfo ASN.1 structure of CMS SignedData 791 * @name KJUR.asn1.cms.SignedData 792 * @class class for Attributes ASN.1 structure of CMS SigndData 793 * @param {Array} params associative array of parameters 794 * @extends KJUR.asn1.ASN1Object 795 * @since jsrsasign 4.2.4 asn1cms 1.0.0 796 * 797 * @description 798 * <pre> 799 * SignedData ::= SEQUENCE { 800 * version CMSVersion, 801 * digestAlgorithms DigestAlgorithmIdentifiers, 802 * encapContentInfo EncapsulatedContentInfo, 803 * certificates [0] IMPLICIT CertificateSet OPTIONAL, 804 * crls [1] IMPLICIT RevocationInfoChoices OPTIONAL, 805 * signerInfos SignerInfos } 806 * SignerInfos ::= SET OF SignerInfo 807 * CertificateSet ::= SET OF CertificateChoices 808 * DigestAlgorithmIdentifiers ::= SET OF DigestAlgorithmIdentifier 809 * CertificateSet ::= SET OF CertificateChoices 810 * RevocationInfoChoices ::= SET OF RevocationInfoChoice 811 * </pre> 812 * 813 * @example 814 * sd = new KJUR.asn1.cms.SignedData(); 815 * sd.dEncapContentInfo.setContentValueStr("test string"); 816 * sd.signerInfoList[0].setForContentAndHash({sdObj: sd, 817 * eciObj: sd.dEncapContentInfo, 818 * hashAlg: 'sha256'}); 819 * sd.signerInfoList[0].dSignedAttrs.add(new KJUR.asn1.cms.SigningTime()); 820 * sd.signerInfoList[0].setSignerIdentifier(certPEM); 821 * sd.signerInfoList[0].sign(prvP8PEM, "SHA256withRSA"); 822 * hex = sd.getContentInfoEncodedHex(); 823 */ 824 KJUR.asn1.cms.SignedData = function(params) { 825 KJUR.asn1.cms.SignedData.superclass.constructor.call(this); 826 var nA = KJUR.asn1; 827 var nC = KJUR.asn1.cms; 828 var nX = KJUR.asn1.x509; 829 830 this.dCMSVersion = new nA.DERInteger({'int': 1}); 831 this.dDigestAlgs = null; 832 this.digestAlgNameList = []; 833 this.dEncapContentInfo = new nC.EncapsulatedContentInfo(); 834 this.dCerts = null; 835 this.certificateList = []; 836 this.crlList = []; 837 this.signerInfoList = [new nC.SignerInfo()]; 838 839 this.addCertificatesByPEM = function(certPEM) { 840 var hex = KEYUTIL.getHexFromPEM(certPEM); 841 var o = new nA.ASN1Object(); 842 o.hTLV = hex; 843 this.certificateList.push(o); 844 }; 845 846 this.getEncodedHex = function() { 847 if (typeof this.hTLV == "string") return this.hTLV; 848 849 if (this.dDigestAlgs == null) { 850 var digestAlgList = []; 851 for (var i = 0; i < this.digestAlgNameList.length; i++) { 852 var name = this.digestAlgNameList[i]; 853 var o = new nX.AlgorithmIdentifier({name: name}); 854 digestAlgList.push(o); 855 } 856 this.dDigestAlgs = new nA.DERSet({array: digestAlgList}); 857 } 858 859 var a = [this.dCMSVersion, 860 this.dDigestAlgs, 861 this.dEncapContentInfo]; 862 863 if (this.dCerts == null) { 864 if (this.certificateList.length > 0) { 865 var o1 = new nA.DERSet({array: this.certificateList}); 866 this.dCerts 867 = new nA.DERTaggedObject({obj: o1, 868 tag: 'a0', 869 explicit: false}); 870 } 871 } 872 if (this.dCerts != null) a.push(this.dCerts); 873 874 var dSignerInfos = new nA.DERSet({array: this.signerInfoList}); 875 a.push(dSignerInfos); 876 877 var seq = new nA.DERSequence({array: a}); 878 this.hTLV = seq.getEncodedHex(); 879 return this.hTLV; 880 }; 881 882 this.getContentInfo = function() { 883 this.getEncodedHex(); 884 var ci = new nC.ContentInfo({type: 'signed-data', obj: this}); 885 return ci; 886 }; 887 888 this.getContentInfoEncodedHex = function() { 889 var ci = this.getContentInfo(); 890 var ciHex = ci.getEncodedHex(); 891 return ciHex; 892 }; 893 894 this.getPEM = function() { 895 var hex = this.getContentInfoEncodedHex(); 896 var pem = nA.ASN1Util.getPEMStringFromHex(hex, "CMS"); 897 return pem; 898 }; 899 }; 900 YAHOO.lang.extend(KJUR.asn1.cms.SignedData, KJUR.asn1.ASN1Object); 901 902 /** 903 * CMS utiliteis class 904 * @name KJUR.asn1.cms.CMSUtil 905 * @class CMS utilities class 906 */ 907 KJUR.asn1.cms.CMSUtil = new function() { 908 }; 909 /** 910 * generate SignedData object specified by JSON parameters 911 * @name newSignedData 912 * @memberOf KJUR.asn1.cms.CMSUtil 913 * @function 914 * @param {Array} param JSON parameter to generate CMS SignedData 915 * @return {KJUR.asn1.cms.SignedData} object just generated 916 * @description 917 * This method provides more easy way to genereate 918 * CMS SignedData ASN.1 structure by JSON data. 919 * @example 920 * var sd = KJUR.asn1.cms.CMSUtil.newSignedData({ 921 * content: {str: "jsrsasign"}, 922 * certs: [certPEM], 923 * signerInfos: [{ 924 * hashAlg: 'sha256', 925 * sAttr: { 926 * SigningTime: {} 927 * SigningCertificateV2: {array: [certPEM]}, 928 * }, 929 * signerCert: certPEM, 930 * sigAlg: 'SHA256withRSA', 931 * signerPrvKey: prvPEM 932 * }] 933 * }); 934 */ 935 KJUR.asn1.cms.CMSUtil.newSignedData = function(param) { 936 var nC = KJUR.asn1.cms; 937 var nE = KJUR.asn1.cades; 938 var sd = new nC.SignedData(); 939 940 sd.dEncapContentInfo.setContentValue(param.content); 941 942 if (typeof param.certs == "object") { 943 for (var i = 0; i < param.certs.length; i++) { 944 sd.addCertificatesByPEM(param.certs[i]); 945 } 946 } 947 948 sd.signerInfoList = []; 949 for (var i = 0; i < param.signerInfos.length; i++) { 950 var siParam = param.signerInfos[i]; 951 var si = new nC.SignerInfo(); 952 si.setSignerIdentifier(siParam.signerCert); 953 954 si.setForContentAndHash({sdObj: sd, 955 eciObj: sd.dEncapContentInfo, 956 hashAlg: siParam.hashAlg}); 957 958 for (attrName in siParam.sAttr) { 959 var attrParam = siParam.sAttr[attrName]; 960 if (attrName == "SigningTime") { 961 var attr = new nC.SigningTime(attrParam); 962 si.dSignedAttrs.add(attr); 963 } 964 if (attrName == "SigningCertificate") { 965 var attr = new nC.SigningCertificate(attrParam); 966 si.dSignedAttrs.add(attr); 967 } 968 if (attrName == "SigningCertificateV2") { 969 var attr = new nC.SigningCertificateV2(attrParam); 970 si.dSignedAttrs.add(attr); 971 } 972 if (attrName == "SignaturePolicyIdentifier") { 973 var attr = new nE.SignaturePolicyIdentifier(attrParam); 974 si.dSignedAttrs.add(attr); 975 } 976 } 977 978 si.sign(siParam.signerPrvKey, siParam.sigAlg); 979 sd.signerInfoList.push(si); 980 } 981 982 return sd; 983 }; 984 985