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