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