1 /* asn1cades-1.0.3.js (c) 2014-2017 Kenji Urushima | kjur.github.com/jsrsasign/license
  2  */
  3 /*
  4  * asn1cades.js - ASN.1 DER encoder classes for RFC 5126 CAdES long term signature
  5  *
  6  * Copyright (c) 2014-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 asn1cades-1.0.js
 18  * @author Kenji Urushima kenji.urushima@gmail.com
 19  * @version jsrsasign 7.2.1 asn1cades 1.0.3 (2017-Jun-03)
 20  * @since jsrsasign 4.7.0
 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 RFC 5126 CAdES long term signature
 42  * <p>
 43  * This name space provides 
 44  * <a href="https://tools.ietf.org/html/rfc5126">RFC 5126
 45  * CAdES(CMS Advanced Electronic Signature)</a> generator.
 46  *
 47  * <h4>SUPPORTED FORMATS</h4>
 48  * Following CAdES formats is supported by this library.
 49  * <ul>
 50  * <li>CAdES-BES - CAdES Basic Electronic Signature</li>
 51  * <li>CAdES-EPES - CAdES Explicit Policy-based Electronic Signature</li>
 52  * <li>CAdES-T - Electronic Signature with Time</li>
 53  * </ul>
 54  * </p>
 55  *
 56  * <h4>PROVIDED ATTRIBUTE CLASSES</h4>
 57  * <ul>
 58  * <li>{@link KJUR.asn1.cades.SignaturePolicyIdentifier} - for CAdES-EPES</li>
 59  * <li>{@link KJUR.asn1.cades.SignatureTimeStamp} - for CAdES-T</li>
 60  * <li>{@link KJUR.asn1.cades.CompleteCertificateRefs} - for CAdES-C(for future use)</li>
 61  * </ul>
 62  * NOTE: Currntly CAdES-C is not supported since parser can't
 63  * handle unsigned attribute.
 64  * 
 65  * <h4>OTHER CLASSES</h4>
 66  * <ul>
 67  * <li>{@link KJUR.asn1.cades.OtherHashAlgAndValue}</li>
 68  * <li>{@link KJUR.asn1.cades.OtherHash}</li>
 69  * <li>{@link KJUR.asn1.cades.OtherCertID}</li>
 70  * <li>{@link KJUR.asn1.cades.CAdESUtil} - utilities for CAdES</li>
 71  * </ul>
 72  *
 73  * <h4>GENERATE CAdES-BES</h4>
 74  * To generate CAdES-BES, {@link KJUR.asn.cades} namespace 
 75  * classes are not required and already {@link KJUR.asn.cms} namespace 
 76  * provides attributes for CAdES-BES.
 77  * Create {@link KJUR.asn1.cms.SignedData} with following
 78  * mandatory attribute in CAdES-BES:
 79  * <ul>
 80  * <li>{@link KJUR.asn1.cms.ContentType}</li>
 81  * <li>{@link KJUR.asn1.cms.MessageDigest}</li>
 82  * <li>{@link KJUR.asn1.cms.SigningCertificate} or </li>
 83  * <li>{@link KJUR.asn1.cms.SigningCertificateV2}</li>
 84  * </ul>
 85  * CMSUtil.newSignedData method is very useful to generate CAdES-BES.
 86  * <pre>
 87  * sd = KJUR.asn1.cms.CMSUtil.newSignedData({
 88  *   content: {str: "aaa"},
 89  *   certs: [certPEM],
 90  *   signerInfos: [{
 91  *     hashAlg: 'sha256',
 92  *     sAttr: {SigningCertificateV2: {array: [certPEM]}},
 93  *     signerCert: certPEM,
 94  *     sigAlg: 'SHA256withRSA',
 95  *     signerPrvKey: pkcs8PrvKeyPEM
 96  *   }]
 97  * });
 98  * signedDataHex = sd.getContentInfoEncodedHex();
 99  * </pre>
100  * NOTE: ContentType and MessageDigest signed attributes
101  * are automatically added by default.
102  *
103  * <h4>GENERATE CAdES-BES with multiple signers</h4>
104  * If you need signature by multiple signers, you can 
105  * specify one or more items in 'signerInfos' property as below.
106  * <pre>
107  * sd = KJUR.asn1.cms.CMSUtil.newSignedData({
108  *   content: {str: "aaa"},
109  *   certs: [certPEM1, certPEM2],
110  *   signerInfos: [{
111  *     hashAlg: 'sha256',
112  *     sAttr: {SigningCertificateV2: {array: [certPEM1]}},
113  *     signerCert: certPEM1,
114  *     sigAlg: 'SHA256withRSA',
115  *     signerPrvKey: pkcs8PrvKeyPEM1
116  *   },{
117  *     hashAlg: 'sha1',
118  *     sAttr: {SigningCertificateV2: {array: [certPEM2]}},
119  *     signerCert: certPEM2,
120  *     sigAlg: 'SHA1withRSA',
121  *     signerPrvKey: pkcs8PrvKeyPEM2
122  *   }]
123  * });
124  * signedDataHex = sd.getContentInfoEncodedHex();
125  * </pre>
126  *
127  * <h4>GENERATE CAdES-EPES</h4>
128  * When you need a CAdES-EPES signature,
129  * you just need to add 'SignaturePolicyIdentifier'
130  * attribute as below.
131  * <pre>
132  * sd = KJUR.asn1.cms.CMSUtil.newSignedData({
133  *   content: {str: "aaa"},
134  *   certs: [certPEM],
135  *   signerInfos: [{
136  *     hashAlg: 'sha256',
137  *     sAttr: {
138  *       SigningCertificateV2: {array: [certPEM]},
139  *       SignaturePolicyIdentifier: {
140  *         oid: '1.2.3.4.5',
141  *         hash: {alg: 'sha1', hash: 'b1b2b3b4b...'}
142  *       },
143  *     },
144  *     signerCert: certPEM,
145  *     sigAlg: 'SHA256withRSA',
146  *     signerPrvKey: pkcs8PrvKeyPEM
147  *   }]
148  * });
149  * signedDataHex = sd.getContentInfoEncodedHex();
150  * </pre>
151  *
152  * <h4>GENERATE CAdES-T</h4>
153  * After a signed CAdES-BES or CAdES-EPES signature have been generated,
154  * you can generate CAdES-T by adding SigningTimeStamp unsigned attribute.
155  * <pre>
156  * beshex = "30..."; // hex of CAdES-BES or EPES data 
157  * info = KJUR.asn1.cades.CAdESUtil.parseSignedDataForAddingUnsigned(beshex);
158  * // You can refer a hexadecimal string of signature value 
159  * // in the first signerInfo in the CAdES-BES/EPES with a variable:
160  * // 'info.si[0].sigval'. You need to get RFC 3161 TimeStampToken
161  * // from a trusted time stamp authority. Otherwise you can also 
162  * // get it by 'KJUR.asn1.tsp' module. We suppose that we could 
163  * // get proper time stamp.
164  * tsthex0 = "30..."; // hex of TimeStampToken for signerInfo[0] sigval
165  * si0 = info.obj.signerInfoList[0];
166  * si0.addUnsigned(new KJUR.asn1.cades.SignatureTimeStamp({tst: tsthex0});
167  * esthex = info.obj.getContentInfoEncodedHex(); // CAdES-T
168  * </pre>
169  * </p>
170  *
171  * <h4>SAMPLE CODES</h4>
172  * <ul>
173  * <li><a href="../../tool_cades.html">demo program for CAdES-BES/EPES/T generation</a></li>
174  * <li><a href="../../test/qunit-do-asn1cades.html">Unit test code for KJUR.asn1.cades package</a></li>
175  * <li><a href="../../test/qunit-do-asn1tsp.html">Unit test code for KJUR.asn1.tsp package (See SimpleTSAAdaptor test)</a></li>
176  * <li><a href="../../test/qunit-do-asn1cms.html">Unit test code for KJUR.asn1.cms package (See newSignedData test)</a></li>
177  * </ul>
178  * 
179  * @name KJUR.asn1.cades
180  * @namespace
181  */
182 if (typeof KJUR.asn1.cades == "undefined" || !KJUR.asn1.cades) KJUR.asn1.cades = {};
183 
184 /**
185  * class for RFC 5126 CAdES SignaturePolicyIdentifier attribute
186  * @name KJUR.asn1.cades.SignaturePolicyIdentifier
187  * @class class for RFC 5126 CAdES SignaturePolicyIdentifier attribute
188  * @param {Array} params associative array of parameters
189  * @extends KJUR.asn1.cms.Attribute
190  * @since jsrsasign 4.7.0 asn1cades 1.0.0
191  * @description
192  * <pre>
193  * SignaturePolicyIdentifier ::= CHOICE {
194  *    signaturePolicyId       SignaturePolicyId,
195  *    signaturePolicyImplied  SignaturePolicyImplied } -- not used
196  *
197  * SignaturePolicyImplied ::= NULL
198  * SignaturePolicyId ::= SEQUENCE {
199  *    sigPolicyId           SigPolicyId,
200  *    sigPolicyHash         SigPolicyHash,
201  *    sigPolicyQualifiers   SEQUENCE SIZE (1..MAX) OF
202  *                             SigPolicyQualifierInfo OPTIONAL }
203  * SigPolicyId ::= OBJECT IDENTIFIER
204  * SigPolicyHash ::= OtherHashAlgAndValue
205  * </pre>
206  * @example
207  * var o = new KJUR.asn1.cades.SignaturePolicyIdentifier({
208  *   oid: '1.2.3.4.5',
209  *   hash: {alg: 'sha1', hash: 'a1a2a3a4...'}
210  * });
211  */
212 /*
213  * id-aa-ets-sigPolicyId OBJECT IDENTIFIER ::= { iso(1)
214  *    member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9)
215  *    smime(16) id-aa(2) 15 }
216  *
217  * signature-policy-identifier attribute values have ASN.1 type
218  * SignaturePolicyIdentifier:
219  *
220  * SigPolicyQualifierInfo ::= SEQUENCE {
221  *    sigPolicyQualifierId  SigPolicyQualifierId,
222  *    sigQualifier          ANY DEFINED BY sigPolicyQualifierId } 
223  *
224  * sigpolicyQualifierIds defined in the present document:
225  * SigPolicyQualifierId ::= OBJECT IDENTIFIER
226  * id-spq-ets-uri OBJECT IDENTIFIER ::= { iso(1)
227  *    member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9)
228  *    smime(16) id-spq(5) 1 }
229  *
230  * SPuri ::= IA5String
231  *
232  * id-spq-ets-unotice OBJECT IDENTIFIER ::= { iso(1)
233  *    member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9)
234  *    smime(16) id-spq(5) 2 }
235  *
236  * SPUserNotice ::= SEQUENCE {
237  *    noticeRef        NoticeReference OPTIONAL,
238  *    explicitText     DisplayText OPTIONAL}
239  *
240  * NoticeReference ::= SEQUENCE {
241  *    organization     DisplayText,
242  *    noticeNumbers    SEQUENCE OF INTEGER }
243  *
244  * DisplayText ::= CHOICE {
245  *    visibleString    VisibleString  (SIZE (1..200)),
246  *    bmpString        BMPString      (SIZE (1..200)),
247  *    utf8String       UTF8String     (SIZE (1..200)) }
248  */
249 KJUR.asn1.cades.SignaturePolicyIdentifier = function(params) {
250     var _KJUR = KJUR,
251 	_KJUR_asn1 = _KJUR.asn1,
252 	_DERObjectIdentifier = _KJUR_asn1.DERObjectIdentifier,
253 	_DERSequence = _KJUR_asn1.DERSequence,
254 	_KJUR_asn1_cades = _KJUR_asn1.cades,
255 	_OtherHashAlgAndValue = _KJUR_asn1_cades.OtherHashAlgAndValue;
256 	
257     _KJUR_asn1_cades.SignaturePolicyIdentifier.superclass.constructor.call(this);
258     this.attrTypeOid = "1.2.840.113549.1.9.16.2.15";
259 
260     if (params !== undefined) {
261         if (typeof params.oid == "string" &&
262             typeof params.hash == "object") {
263             var dOid = new _DERObjectIdentifier({oid: params.oid});
264             var dHash = new _OtherHashAlgAndValue(params.hash);
265             var seq = new _DERSequence({array: [dOid, dHash]});
266             this.valueList = [seq];
267         }
268     }
269 };
270 YAHOO.lang.extend(KJUR.asn1.cades.SignaturePolicyIdentifier,
271                   KJUR.asn1.cms.Attribute);
272 
273 /**
274  * class for OtherHashAlgAndValue ASN.1 object
275  * @name KJUR.asn1.cades.OtherHashAlgAndValue
276  * @class class for OtherHashAlgAndValue ASN.1 object
277  * @param {Array} params associative array of parameters
278  * @extends KJUR.asn1.ASN1Object
279  * @since jsrsasign 4.7.0 asn1cades 1.0.0
280  * @description
281  * <pre>
282  * OtherHashAlgAndValue ::= SEQUENCE {
283  *    hashAlgorithm   AlgorithmIdentifier,
284  *    hashValue       OtherHashValue }
285  * OtherHashValue ::= OCTET STRING
286  * </pre>
287  */
288 KJUR.asn1.cades.OtherHashAlgAndValue = function(params) {
289     var _KJUR = KJUR,
290 	_KJUR_asn1 = _KJUR.asn1,
291 	_DERSequence = _KJUR_asn1.DERSequence,
292 	_DEROctetString = _KJUR_asn1.DEROctetString,
293 	_KJUR_asn1_x509 = _KJUR_asn1.x509,
294 	_AlgorithmIdentifier = _KJUR_asn1_x509.AlgorithmIdentifier,
295 	_KJUR_asn1_cades = _KJUR_asn1.cades,
296 	_OtherHashAlgAndValue = _KJUR_asn1_cades.OtherHashAlgAndValue;
297 
298     _OtherHashAlgAndValue.superclass.constructor.call(this);
299 
300     this.dAlg = null;
301     this.dHash = null;
302 
303     this.getEncodedHex = function() {
304         var seq = new _DERSequence({array: [this.dAlg, this.dHash]});
305         this.hTLV = seq.getEncodedHex();
306         return this.hTLV;
307     };
308 
309     if (params !== undefined) {
310         if (typeof params.alg == "string" &&
311             typeof params.hash == "string") {
312             this.dAlg = new _AlgorithmIdentifier({name: params.alg});
313             this.dHash = new _DEROctetString({hex: params.hash});
314         }
315     }
316 };
317 YAHOO.lang.extend(KJUR.asn1.cades.OtherHashAlgAndValue, KJUR.asn1.ASN1Object);
318 
319 /**
320  * class for RFC 5126 CAdES SignatureTimeStamp attribute
321  * @name KJUR.asn1.cades.SignatureTimeStamp
322  * @class class for RFC 5126 CAdES SignatureTimeStamp attribute
323  * @param {Array} params associative array of parameters
324  * @extends KJUR.asn1.cms.Attribute
325  * @since jsrsasign 4.7.0 asn1cades 1.0.0
326  * @description
327  * <pre>
328  * id-aa-signatureTimeStampToken OBJECT IDENTIFIER ::=
329  *    1.2.840.113549.1.9.16.2.14
330  * SignatureTimeStampToken ::= TimeStampToken
331  * </pre>
332  */
333 KJUR.asn1.cades.SignatureTimeStamp = function(params) {
334     var _KJUR = KJUR,
335 	_KJUR_asn1 = _KJUR.asn1,
336 	_ASN1Object = _KJUR_asn1.ASN1Object,
337 	_KJUR_asn1_x509 = _KJUR_asn1.x509,
338 	_KJUR_asn1_cades = _KJUR_asn1.cades;
339 
340     _KJUR_asn1_cades.SignatureTimeStamp.superclass.constructor.call(this);
341     this.attrTypeOid = "1.2.840.113549.1.9.16.2.14";
342     this.tstHex = null;
343 
344     if (params !== undefined) {
345         if (params.res !== undefined) {
346             if (typeof params.res == "string" &&
347                 params.res.match(/^[0-9A-Fa-f]+$/)) {
348             } else if (params.res instanceof _ASN1Object) {
349             } else {
350                 throw "res param shall be ASN1Object or hex string";
351             }
352         }
353         if (params.tst !== undefined) {
354             if (typeof params.tst == "string" &&
355                 params.tst.match(/^[0-9A-Fa-f]+$/)) {
356                 var d = new _ASN1Object();
357                 this.tstHex = params.tst;
358                 d.hTLV = this.tstHex;
359                 d.getEncodedHex();
360                 this.valueList = [d];
361             } else if (params.tst instanceof _ASN1Object) {
362             } else {
363                 throw "tst param shall be ASN1Object or hex string";
364             }
365         }
366     }
367 };
368 YAHOO.lang.extend(KJUR.asn1.cades.SignatureTimeStamp,
369                   KJUR.asn1.cms.Attribute);
370 
371 /**
372  * class for RFC 5126 CAdES CompleteCertificateRefs attribute
373  * @name KJUR.asn1.cades.CompleteCertificateRefs
374  * @class class for RFC 5126 CAdES CompleteCertificateRefs attribute
375  * @param {Array} params associative array of parameters
376  * @extends KJUR.asn1.cms.Attribute
377  * @since jsrsasign 4.7.0 asn1cades 1.0.0
378  * @description
379  * <pre>
380  * id-aa-ets-certificateRefs OBJECT IDENTIFIER = 
381  *    1.2.840.113549.1.9.16.2.21
382  * CompleteCertificateRefs ::=  SEQUENCE OF OtherCertID
383  * </pre>
384  * @example
385  * o = new KJUR.asn1.cades.CompleteCertificateRefs([certPEM1,certPEM2]);
386  */
387 KJUR.asn1.cades.CompleteCertificateRefs = function(params) {
388     var _KJUR = KJUR,
389 	_KJUR_asn1 = _KJUR.asn1,
390 	_KJUR_asn1_cades = _KJUR_asn1.cades;
391 
392     _KJUR_asn1_cades.CompleteCertificateRefs.superclass.constructor.call(this);
393     this.attrTypeOid = "1.2.840.113549.1.9.16.2.21";
394 
395     /**
396      * set value by array
397      * @name setByArray
398      * @memberOf KJUR.asn1.cades.CompleteCertificateRefs
399      * @function
400      * @param {Array} a array of {@link KJUR.asn1.cades.OtherCertID} argument
401      * @return unspecified
402      * @description
403      */
404     this.setByArray = function(a) {
405         this.valueList = [];
406         for (var i = 0; i < a.length; i++) {
407             var o = new _KJUR_asn1_cades.OtherCertID(a[i]);
408             this.valueList.push(o);
409         }
410     };
411 
412     if (params !== undefined) {
413         if (typeof params == "object" &&
414             typeof params.length == "number") {
415             this.setByArray(params);
416         }
417     }
418 };
419 YAHOO.lang.extend(KJUR.asn1.cades.CompleteCertificateRefs,
420                   KJUR.asn1.cms.Attribute);
421 
422 /**
423  * class for OtherCertID ASN.1 object
424  * @name KJUR.asn1.cades.OtherCertID
425  * @class class for OtherCertID ASN.1 object
426  * @param {Array} params associative array of parameters
427  * @extends KJUR.asn1.ASN1Object
428  * @since jsrsasign 4.7.0 asn1cades 1.0.0
429  * @description
430  * <pre>
431  * OtherCertID ::= SEQUENCE {
432  *    otherCertHash    OtherHash,
433  *    issuerSerial     IssuerSerial OPTIONAL }
434  * </pre>
435  * @example
436  * o = new KJUR.asn1.cades.OtherCertID(certPEM);
437  * o = new KJUR.asn1.cades.OtherCertID({cert:certPEM, hasis: false});
438  */
439 KJUR.asn1.cades.OtherCertID = function(params) {
440     var _KJUR = KJUR,
441 	_KJUR_asn1 = _KJUR.asn1,
442 	_KJUR_asn1_cms = _KJUR_asn1.cms,
443 	_KJUR_asn1_cades = _KJUR_asn1.cades;
444 
445     _KJUR_asn1_cades.OtherCertID.superclass.constructor.call(this);
446 
447     this.hasIssuerSerial = true;
448     this.dOtherCertHash = null;
449     this.dIssuerSerial = null;
450 
451     /**
452      * set value by PEM string of certificate
453      * @name setByCertPEM
454      * @memberOf KJUR.asn1.cades.OtherCertID
455      * @function
456      * @param {String} certPEM PEM string of certificate
457      * @return unspecified
458      * @description
459      * This method will set value by a PEM string of a certificate.
460      * This will add IssuerAndSerialNumber by default 
461      * which depends on hasIssuerSerial flag.
462      */
463     this.setByCertPEM = function(certPEM) {
464         this.dOtherCertHash = new _KJUR_asn1_cades.OtherHash(certPEM);
465         if (this.hasIssuerSerial)
466             this.dIssuerSerial = 
467 	        new _KJUR_asn1_cms.IssuerAndSerialNumber(certPEM);
468     };
469 
470     this.getEncodedHex = function() {
471         if (this.hTLV != null) return this.hTLV;
472         if (this.dOtherCertHash == null)
473             throw "otherCertHash not set";
474         var a = [this.dOtherCertHash];
475         if (this.dIssuerSerial != null)
476             a.push(this.dIssuerSerial);
477         var seq = new _KJUR_asn1.DERSequence({array: a});
478         this.hTLV = seq.getEncodedHex();
479         return this.hTLV;
480     };
481 
482     if (params !== undefined) {
483         if (typeof params == "string" &&
484             params.indexOf("-----BEGIN ") != -1) {
485             this.setByCertPEM(params);
486         }
487         if (typeof params == "object") {
488             if (params.hasis === false)
489                 this.hasIssuerSerial = false;
490             if (typeof params.cert == "string")
491                 this.setByCertPEM(params.cert);
492         }
493     }
494 };
495 YAHOO.lang.extend(KJUR.asn1.cades.OtherCertID, KJUR.asn1.ASN1Object);
496 
497 /**
498  * class for OtherHash ASN.1 object
499  * @name KJUR.asn1.cades.OtherHash
500  * @class class for OtherHash ASN.1 object
501  * @param {Array} params associative array of parameters
502  * @extends KJUR.asn1.ASN1Object
503  * @since jsrsasign 4.7.0 asn1cades 1.0.0
504  * @description
505  * <pre>
506  * OtherHash ::= CHOICE {
507  *    sha1Hash   OtherHashValue,  -- This contains a SHA-1 hash
508  *    otherHash  OtherHashAlgAndValue}
509  * OtherHashValue ::= OCTET STRING
510  * </pre>
511  * @example
512  * o = new KJUR.asn1.cades.OtherHash("1234");
513  * o = new KJUR.asn1.cades.OtherHash(certPEMStr); // default alg=sha256
514  * o = new KJUR.asn1.cades.OtherHash({alg: 'sha256', hash: '1234'});
515  * o = new KJUR.asn1.cades.OtherHash({alg: 'sha256', cert: certPEM});
516  * o = new KJUR.asn1.cades.OtherHash({cert: certPEM});
517  */
518 KJUR.asn1.cades.OtherHash = function(params) {
519     var _KJUR = KJUR,
520 	_KJUR_asn1 = _KJUR.asn1,
521 	_KJUR_asn1_cms = _KJUR_asn1.cms,
522 	_KJUR_asn1_cades = _KJUR_asn1.cades,
523 	_OtherHashAlgAndValue = _KJUR_asn1_cades.OtherHashAlgAndValue,
524 	_hashHex = _KJUR.crypto.Util.hashHex;
525 
526     _KJUR_asn1_cades.OtherHash.superclass.constructor.call(this);
527 
528     this.alg = 'sha256';
529     this.dOtherHash = null;
530 
531     /**
532      * set value by PEM string of certificate
533      * @name setByCertPEM
534      * @memberOf KJUR.asn1.cades.OtherHash
535      * @function
536      * @param {String} certPEM PEM string of certificate
537      * @return unspecified
538      * @description
539      * This method will set value by a PEM string of a certificate.
540      * An algorithm used to hash certificate data will
541      * be defined by 'alg' property and 'sha256' is default.
542      */
543     this.setByCertPEM = function(certPEM) {
544         if (certPEM.indexOf("-----BEGIN ") == -1)
545             throw "certPEM not to seem PEM format";
546         var hex = pemtohex(certPEM);
547         var hash = _hashHex(hex, this.alg);
548         this.dOtherHash = 
549             new _OtherHashAlgAndValue({alg: this.alg, hash: hash});
550     };
551 
552     this.getEncodedHex = function() {
553         if (this.dOtherHash == null)
554             throw "OtherHash not set";
555         return this.dOtherHash.getEncodedHex();
556     };
557 
558     if (params !== undefined) {
559         if (typeof params == "string") {
560             if (params.indexOf("-----BEGIN ") != -1) {
561                 this.setByCertPEM(params);
562             } else if (params.match(/^[0-9A-Fa-f]+$/)) {
563                 this.dOtherHash = new _KJUR_asn1.DEROctetString({hex: params});
564             } else {
565                 throw "unsupported string value for params";
566             }
567         } else if (typeof params == "object") {
568             if (typeof params.cert == "string") {
569                 if (typeof params.alg == "string")
570                     this.alg = params.alg;
571                 this.setByCertPEM(params.cert);
572             } else {
573                 this.dOtherHash = new _OtherHashAlgAndValue(params);
574             }
575         }
576     }
577 };
578 YAHOO.lang.extend(KJUR.asn1.cades.OtherHash, KJUR.asn1.ASN1Object);
579 
580 
581 // == BEGIN UTILITIES =====================================================
582 
583 /**
584  * CAdES utiliteis class
585  * @name KJUR.asn1.cades.CAdESUtil
586  * @class CAdES utilities class
587  * @since jsrsasign 4.7.0 asn1cades 1.0.0
588  */
589 KJUR.asn1.cades.CAdESUtil = new function() {
590 };
591 /*
592  *
593  */
594 KJUR.asn1.cades.CAdESUtil.addSigTS = function(dCMS, siIdx, sigTSHex) {
595 };
596 /**
597  * parse CMS SignedData to add unsigned attributes
598  * @name parseSignedDataForAddingUnsigned
599  * @memberOf KJUR.asn1.cades.CAdESUtil
600  * @function
601  * @param {String} hex hexadecimal string of ContentInfo of CMS SignedData
602  * @return {Object} associative array of parsed data
603  * @description
604  * This method will parse a hexadecimal string of 
605  * ContentInfo with CMS SignedData to add a attribute
606  * to unsigned attributes field in a signerInfo field.
607  * Parsed result will be an associative array which has
608  * following properties:
609  * <ul>
610  * <li>version - hex of CMSVersion ASN.1 TLV</li>
611  * <li>algs - hex of DigestAlgorithms ASN.1 TLV</li>
612  * <li>encapcontent - hex of EncapContentInfo ASN.1 TLV</li>
613  * <li>certs - hex of Certificates ASN.1 TLV</li>
614  * <li>revs - hex of RevocationInfoChoices ASN.1 TLV</li>
615  * <li>si[] - array of SignerInfo properties</li>
616  * <li>obj - parsed KJUR.asn1.cms.SignedData object</li>
617  * </ul>
618  * @example
619  * info = KJUR.asn1.cades.CAdESUtil.parseSignedDataForAddingUnsigned(beshex);
620  * sd = info.obj;
621  */
622 KJUR.asn1.cades.CAdESUtil.parseSignedDataForAddingUnsigned = function(hex) {
623     var _ASN1HEX = ASN1HEX,
624 	_getChildIdx = _ASN1HEX.getChildIdx,
625 	_getTLV = _ASN1HEX.getTLV,
626 	_getTLVbyList = _ASN1HEX.getTLVbyList,
627 	_getIdxbyList = _ASN1HEX.getIdxbyList,
628 	_KJUR = KJUR,
629 	_KJUR_asn1 = _KJUR.asn1,
630 	_ASN1Object = _KJUR_asn1.ASN1Object,
631 	_KJUR_asn1_cms = _KJUR_asn1.cms,
632 	_SignedData = _KJUR_asn1_cms.SignedData,
633 	_KJUR_asn1_cades = _KJUR_asn1.cades,
634 	_CAdESUtil = _KJUR_asn1_cades.CAdESUtil;
635     
636     var r = {};
637 
638     // 1. not oid signed-data then error
639     if (_getTLVbyList(hex, 0, [0]) != "06092a864886f70d010702")
640         throw "hex is not CMS SignedData";
641 
642     var iSD = _getIdxbyList(hex, 0, [1, 0]);
643     var aSDChildIdx = _getChildIdx(hex, iSD);
644     if (aSDChildIdx.length < 4)
645         throw "num of SignedData elem shall be 4 at least";
646 
647     // 2. HEXs of SignedData children
648     // 2.1. SignedData.CMSVersion
649     var iVersion = aSDChildIdx.shift();
650     r.version = _getTLV(hex, iVersion);
651 
652     // 2.2. SignedData.DigestAlgorithms
653     var iAlgs = aSDChildIdx.shift();
654     r.algs = _getTLV(hex, iAlgs);
655 
656     // 2.3. SignedData.EncapContentInfo
657     var iEncapContent = aSDChildIdx.shift();
658     r.encapcontent = _getTLV(hex, iEncapContent);
659 
660     // 2.4. [0]Certs 
661     r.certs = null;
662     r.revs = null;
663     r.si = [];
664 
665     var iNext = aSDChildIdx.shift();
666     if (hex.substr(iNext, 2) == "a0") {
667         r.certs = _getTLV(hex, iNext);
668         iNext = aSDChildIdx.shift();
669     }
670 
671     // 2.5. [1]Revs
672     if (hex.substr(iNext, 2) == "a1") {
673         r.revs = _getTLV(hex, iNext);
674         iNext = aSDChildIdx.shift();
675     }
676 
677     // 2.6. SignerInfos
678     var iSignerInfos = iNext;
679     if (hex.substr(iSignerInfos, 2) != "31")
680         throw "Can't find signerInfos";
681 
682     var aSIIndex = _getChildIdx(hex, iSignerInfos);
683     //alert(aSIIndex.join("-"));
684 
685     for (var i = 0; i < aSIIndex.length; i++) {
686         var iSI = aSIIndex[i];
687         var pSI = _CAdESUtil.parseSignerInfoForAddingUnsigned(hex, iSI, i);
688         r.si[i] = pSI;
689     }
690 
691     // x. obj(SignedData)
692     var tmp = null;
693     r.obj = new _SignedData();
694 
695     tmp = new _ASN1Object();
696     tmp.hTLV = r.version;
697     r.obj.dCMSVersion = tmp;
698 
699     tmp = new _ASN1Object();
700     tmp.hTLV = r.algs;
701     r.obj.dDigestAlgs = tmp;
702 
703     tmp = new _ASN1Object();
704     tmp.hTLV = r.encapcontent;
705     r.obj.dEncapContentInfo = tmp;
706 
707     tmp = new _ASN1Object();
708     tmp.hTLV = r.certs;
709     r.obj.dCerts = tmp;
710 
711     r.obj.signerInfoList = [];
712     for (var i = 0; i < r.si.length; i++) {
713         r.obj.signerInfoList.push(r.si[i].obj);
714     }
715 
716     return r;
717 };
718 
719 /**
720  * parse SignerInfo to add unsigned attributes
721  * @name parseSignerInfoForAddingUnsigned
722  * @memberOf KJUR.asn1.cades.CAdESUtil
723  * @function
724  * @param {String} hex hexadecimal string of SignerInfo
725  * @return {Object} associative array of parsed data
726  * @description
727  * This method will parse a hexadecimal string of 
728  * SignerInfo to add a attribute
729  * to unsigned attributes field in a signerInfo field.
730  * Parsed result will be an associative array which has
731  * following properties:
732  * <ul>
733  * <li>version - hex TLV of version</li>
734  * <li>si - hex TLV of SignerIdentifier</li>
735  * <li>digalg - hex TLV of DigestAlgorithm</li>
736  * <li>sattrs - hex TLV of SignedAttributes</li>
737  * <li>sigalg - hex TLV of SignatureAlgorithm</li>
738  * <li>sig - hex TLV of signature</li>
739  * <li>sigval = hex V of signature</li>
740  * <li>obj - parsed KJUR.asn1.cms.SignerInfo object</li>
741  * </ul>
742  * NOTE: Parsing of unsigned attributes will be provided in the
743  * future version. That's way this version provides support
744  * for CAdES-T and not for CAdES-C.
745  */
746 KJUR.asn1.cades.CAdESUtil.parseSignerInfoForAddingUnsigned = function(hex, iSI, nth) {
747     var _ASN1HEX = ASN1HEX,
748 	_getChildIdx = _ASN1HEX.getChildIdx,
749 	_getTLV = _ASN1HEX.getTLV,
750 	_getV = _ASN1HEX.getV,
751 	_KJUR = KJUR,
752 	_KJUR_asn1 = _KJUR.asn1,
753 	_ASN1Object = _KJUR_asn1.ASN1Object,
754 	_KJUR_asn1_cms = _KJUR_asn1.cms,
755 	_AttributeList = _KJUR_asn1_cms.AttributeList,
756 	_SignerInfo = _KJUR_asn1_cms.SignerInfo;
757 
758     var r = {};
759     var aSIChildIdx = _getChildIdx(hex, iSI);
760     //alert(aSIChildIdx.join("="));
761 
762     if (aSIChildIdx.length != 6)
763         throw "not supported items for SignerInfo (!=6)"; 
764 
765     // 1. SignerInfo.CMSVersion
766     var iVersion = aSIChildIdx.shift();
767     r.version = _getTLV(hex, iVersion);
768 
769     // 2. SignerIdentifier(IssuerAndSerialNumber)
770     var iIdentifier = aSIChildIdx.shift();
771     r.si = _getTLV(hex, iIdentifier);
772 
773     // 3. DigestAlgorithm
774     var iDigestAlg = aSIChildIdx.shift();
775     r.digalg = _getTLV(hex, iDigestAlg);
776 
777     // 4. SignedAttrs
778     var iSignedAttrs = aSIChildIdx.shift();
779     r.sattrs = _getTLV(hex, iSignedAttrs);
780 
781     // 5. SigAlg
782     var iSigAlg = aSIChildIdx.shift();
783     r.sigalg = _getTLV(hex, iSigAlg);
784 
785     // 6. Signature
786     var iSig = aSIChildIdx.shift();
787     r.sig = _getTLV(hex, iSig);
788     r.sigval = _getV(hex, iSig);
789 
790     // 7. obj(SignerInfo)
791     var tmp = null;
792     r.obj = new _SignerInfo();
793 
794     tmp = new _ASN1Object();
795     tmp.hTLV = r.version;
796     r.obj.dCMSVersion = tmp;
797 
798     tmp = new _ASN1Object();
799     tmp.hTLV = r.si;
800     r.obj.dSignerIdentifier = tmp;
801 
802     tmp = new _ASN1Object();
803     tmp.hTLV = r.digalg;
804     r.obj.dDigestAlgorithm = tmp;
805 
806     tmp = new _ASN1Object();
807     tmp.hTLV = r.sattrs;
808     r.obj.dSignedAttrs = tmp;
809 
810     tmp = new _ASN1Object();
811     tmp.hTLV = r.sigalg;
812     r.obj.dSigAlg = tmp;
813 
814     tmp = new _ASN1Object();
815     tmp.hTLV = r.sig;
816     r.obj.dSig = tmp;
817 
818     r.obj.dUnsignedAttrs = new _AttributeList();
819 
820     return r;
821 };
822 
823