From 801ee38d5d452f2b8f46ba0fd3dc859889746991 Mon Sep 17 00:00:00 2001 From: Kenji Urushima Date: Tue, 17 May 2016 23:49:01 +0900 Subject: [PATCH] 5.0.12 release --- ChangeLog.txt | 8 + api/files.html | 2 +- api/symbols/ASN1HEX.html | 42 +- api/symbols/KJUR.jws.JWS.html | 24 +- api/symbols/src/asn1hex-1.1.js.html | 1091 ++++++++++++++------------- api/symbols/src/jws-3.3.js.html | 988 ++++++++++++------------ asn1hex-1.1.js | 43 +- bower.json | 2 +- jsrsasign-latest-all-min.js | 6 +- jws-3.3.js | 48 +- min/jws-3.3.min.js | 4 +- npm/lib/jsrsasign.js | 6 +- npm/package.json | 2 +- test/qunit-do-jwt-veri.html | 25 +- 14 files changed, 1241 insertions(+), 1050 deletions(-) diff --git a/ChangeLog.txt b/ChangeLog.txt index 5a1c1555..f61f8c0d 100755 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -1,6 +1,14 @@ ChangeLog for jsrsasign +* Changes between 5.0.11 to 5.0.12 + - jws between 3.3.3 to 3.3.4 + - support grace period for verifyJWT method. + This is to allow time difference between + JWT generator and verifier. + - asn1hex + - API document update + * Changes between 5.0.10 to 5.0.11 - X509v1 certificate support in KEYUTIL.getKey and X509.getPublicKeyInfoPropOfCertPEM diff --git a/api/files.html b/api/files.html index beb8dd91..14865e34 100644 --- a/api/files.html +++ b/api/files.html @@ -649,7 +649,7 @@

jws-3.3.js

Version:
-
3.3.3 (2015-Nov-27)
+
3.3.4 (2016-May-17)
diff --git a/api/symbols/ASN1HEX.html b/api/symbols/ASN1HEX.html index 3a3ab6c5..99fc515c 100644 --- a/api/symbols/ASN1HEX.html +++ b/api/symbols/ASN1HEX.html @@ -448,7 +448,9 @@

-
ASN.1 DER encoded hexadecimal string utility class
+
ASN.1 DER encoded hexadecimal string utility class +This class provides a parser for hexadecimal string of +DER encoded ASN.1 binary data.
@@ -633,6 +635,41 @@

ASN.1 DER encoded hexadecimal string utility class +This class provides a parser for hexadecimal string of +DER encoded ASN.1 binary data. +Here are major methods of this class. +
@@ -700,16 +737,19 @@

ASN1HEX.dump('0203012345') ↓ INTEGER 012345 + // ASN.1 Object Identifier ASN1HEX.dump('06052b0e03021a') ↓ ObjectIdentifier sha1 (1 3 14 3 2 26) + // ASN.1 SEQUENCE ASN1HEX.dump('3006020101020102') ↓ SEQUENCE INTEGER 01 INTEGER 02 + // ASN.1 DUMP FOR X.509 CERTIFICATE ASN1HEX.dump(X509.pemToHex(certPEM)) ↓ diff --git a/api/symbols/KJUR.jws.JWS.html b/api/symbols/KJUR.jws.JWS.html index 1cd310ef..e604de5b 100644 --- a/api/symbols/KJUR.jws.JWS.html +++ b/api/symbols/KJUR.jws.JWS.html @@ -1518,11 +1518,22 @@

Supported Algorithms

the same as value if specified. (OPTION)
  • Time validity
  • Payload.jti (JWT id) - Payload.jti is included in acceptField.jti if specified. (OPTION)
  • @@ -1545,7 +1556,8 @@

    Supported Algorithms

    sub: ['mailto:john@foo.com', 'mailto:alice@foo.com'], verifyAt: KJUR.jws.IntDate.get('20150520235959Z'), aud: ['http://foo.com'], // aud: 'http://foo.com' is fine too. - jti: 'id123456' + jti: 'id123456', + gracePeriod: 1 * 60 * 60 // accept 1 hour slow or fast }); diff --git a/api/symbols/src/asn1hex-1.1.js.html b/api/symbols/src/asn1hex-1.1.js.html index 2dc8e4a8..7e3f7ae5 100644 --- a/api/symbols/src/asn1hex-1.1.js.html +++ b/api/symbols/src/asn1hex-1.1.js.html @@ -5,12 +5,12 @@ .STRN {color: #393;} .REGX {color: #339;} .line {border-right: 1px dotted #666; color: #666; font-style: normal;} -
      1 /*! asn1hex-1.1.6.js (c) 2012-2015 Kenji Urushima | kjur.github.com/jsrsasign/license
    +	
      1 /*! asn1hex-1.1.6.js (c) 2012-2016 Kenji Urushima | kjur.github.com/jsrsasign/license
       2  */
       3 /*
       4  * asn1hex.js - Hexadecimal represented ASN.1 string library
       5  *
    -  6  * Copyright (c) 2010-2015 Kenji Urushima (kenji.urushima@gmail.com)
    +  6  * Copyright (c) 2010-2016 Kenji Urushima (kenji.urushima@gmail.com)
       7  *
       8  * This software is licensed under the terms of the MIT License.
       9  * http://kjur.github.com/jsrsasign/license/
    @@ -45,530 +45,569 @@
      38  * @name ASN1HEX
      39  * @class ASN.1 DER encoded hexadecimal string utility class
      40  * @since jsrsasign 1.1
    - 41  */
    - 42 var ASN1HEX = new function() {
    - 43     /**
    - 44      * get byte length for ASN.1 L(length) bytes
    - 45      * @name getByteLengthOfL_AtObj
    - 46      * @memberOf ASN1HEX
    - 47      * @function
    - 48      * @param {String} s hexadecimal string of ASN.1 DER encoded data
    - 49      * @param {Number} pos string index
    - 50      * @return byte length for ASN.1 L(length) bytes
    - 51      */
    - 52     this.getByteLengthOfL_AtObj = function(s, pos) {
    - 53         if (s.substring(pos + 2, pos + 3) != '8') return 1;
    - 54         var i = parseInt(s.substring(pos + 3, pos + 4));
    - 55         if (i == 0) return -1;          // length octet '80' indefinite length
    - 56         if (0 < i && i < 10) return i + 1;      // including '8?' octet;
    - 57         return -2;                              // malformed format
    - 58     };
    - 59 
    - 60     /**
    - 61      * get hexadecimal string for ASN.1 L(length) bytes
    - 62      * @name getHexOfL_AtObj
    - 63      * @memberOf ASN1HEX
    - 64      * @function
    - 65      * @param {String} s hexadecimal string of ASN.1 DER encoded data
    - 66      * @param {Number} pos string index
    - 67      * @return {String} hexadecimal string for ASN.1 L(length) bytes
    - 68      */
    - 69     this.getHexOfL_AtObj = function(s, pos) {
    - 70         var len = this.getByteLengthOfL_AtObj(s, pos);
    - 71         if (len < 1) return '';
    - 72         return s.substring(pos + 2, pos + 2 + len * 2);
    - 73     };
    - 74 
    - 75     //   getting ASN.1 length value at the position 'idx' of
    - 76     //   hexa decimal string 's'.
    - 77     //
    - 78     //   f('3082025b02...', 0) ... 82025b ... ???
    - 79     //   f('020100', 0) ... 01 ... 1
    - 80     //   f('0203001...', 0) ... 03 ... 3
    - 81     //   f('02818003...', 0) ... 8180 ... 128
    - 82     /**
    - 83      * get integer value of ASN.1 length for ASN.1 data
    - 84      * @name getIntOfL_AtObj
    - 85      * @memberOf ASN1HEX
    - 86      * @function
    - 87      * @param {String} s hexadecimal string of ASN.1 DER encoded data
    - 88      * @param {Number} pos string index
    - 89      * @return ASN.1 L(length) integer value
    - 90      */
    - 91     this.getIntOfL_AtObj = function(s, pos) {
    - 92         var hLength = this.getHexOfL_AtObj(s, pos);
    - 93         if (hLength == '') return -1;
    - 94         var bi;
    - 95         if (parseInt(hLength.substring(0, 1)) < 8) {
    - 96             bi = new BigInteger(hLength, 16);
    - 97         } else {
    - 98             bi = new BigInteger(hLength.substring(2), 16);
    - 99         }
    -100         return bi.intValue();
    -101     };
    -102 
    -103     /**
    -104      * get ASN.1 value starting string position for ASN.1 object refered by index 'idx'.
    -105      * @name getStartPosOfV_AtObj
    -106      * @memberOf ASN1HEX
    -107      * @function
    -108      * @param {String} s hexadecimal string of ASN.1 DER encoded data
    -109      * @param {Number} pos string index
    -110      */
    -111     this.getStartPosOfV_AtObj = function(s, pos) {
    -112         var l_len = this.getByteLengthOfL_AtObj(s, pos);
    -113         if (l_len < 0) return l_len;
    -114         return pos + (l_len + 1) * 2;
    -115     };
    -116 
    -117     /**
    -118      * get hexadecimal string of ASN.1 V(value)
    -119      * @name getHexOfV_AtObj
    -120      * @memberOf ASN1HEX
    -121      * @function
    -122      * @param {String} s hexadecimal string of ASN.1 DER encoded data
    -123      * @param {Number} pos string index
    -124      * @return {String} hexadecimal string of ASN.1 value.
    -125      */
    -126     this.getHexOfV_AtObj = function(s, pos) {
    -127         var pos1 = this.getStartPosOfV_AtObj(s, pos);
    -128         var len = this.getIntOfL_AtObj(s, pos);
    -129         return s.substring(pos1, pos1 + len * 2);
    -130     };
    -131 
    -132     /**
    -133      * get hexadecimal string of ASN.1 TLV at
    -134      * @name getHexOfTLV_AtObj
    -135      * @memberOf ASN1HEX
    -136      * @function
    -137      * @param {String} s hexadecimal string of ASN.1 DER encoded data
    -138      * @param {Number} pos string index
    -139      * @return {String} hexadecimal string of ASN.1 TLV.
    -140      * @since 1.1
    -141      */
    -142     this.getHexOfTLV_AtObj = function(s, pos) {
    -143         var hT = s.substr(pos, 2);
    -144         var hL = this.getHexOfL_AtObj(s, pos);
    -145         var hV = this.getHexOfV_AtObj(s, pos);
    -146         return hT + hL + hV;
    -147     };
    -148 
    -149     /**
    -150      * get next sibling starting index for ASN.1 object string
    -151      * @name getPosOfNextSibling_AtObj
    -152      * @memberOf ASN1HEX
    -153      * @function
    -154      * @param {String} s hexadecimal string of ASN.1 DER encoded data
    -155      * @param {Number} pos string index
    -156      * @return next sibling starting index for ASN.1 object string
    -157      */
    -158     this.getPosOfNextSibling_AtObj = function(s, pos) {
    -159         var pos1 = this.getStartPosOfV_AtObj(s, pos);
    -160         var len = this.getIntOfL_AtObj(s, pos);
    -161         return pos1 + len * 2;
    -162     };
    -163 
    -164     /**
    -165      * get array of indexes of child ASN.1 objects
    -166      * @name getPosArrayOfChildren_AtObj
    -167      * @memberOf ASN1HEX
    -168      * @function
    -169      * @param {String} s hexadecimal string of ASN.1 DER encoded data
    -170      * @param {Number} start string index of ASN.1 object
    -171      * @return {Array of Number} array of indexes for childen of ASN.1 objects
    -172      */
    -173     this.getPosArrayOfChildren_AtObj = function(h, pos) {
    -174         var a = new Array();
    -175         var p0 = this.getStartPosOfV_AtObj(h, pos);
    -176         a.push(p0);
    -177 
    -178         var len = this.getIntOfL_AtObj(h, pos);
    -179         var p = p0;
    -180         var k = 0;
    -181         while (1) {
    -182             var pNext = this.getPosOfNextSibling_AtObj(h, p);
    -183             if (pNext == null || (pNext - p0  >= (len * 2))) break;
    -184             if (k >= 200) break;
    -185             
    -186             a.push(pNext);
    -187             p = pNext;
    -188             
    -189             k++;
    -190         }
    -191         
    -192         return a;
    -193     };
    -194 
    -195     /**
    -196      * get string index of nth child object of ASN.1 object refered by h, idx
    -197      * @name getNthChildIndex_AtObj
    -198      * @memberOf ASN1HEX
    -199      * @function
    -200      * @param {String} h hexadecimal string of ASN.1 DER encoded data
    -201      * @param {Number} idx start string index of ASN.1 object
    -202      * @param {Number} nth for child
    -203      * @return {Number} string index of nth child.
    -204      * @since 1.1
    -205      */
    -206     this.getNthChildIndex_AtObj = function(h, idx, nth) {
    -207         var a = this.getPosArrayOfChildren_AtObj(h, idx);
    -208         return a[nth];
    -209     };
    -210 
    -211     // ========== decendant methods ==============================
    -212     /**
    -213      * get string index of nth child object of ASN.1 object refered by h, idx
    -214      * @name getDecendantIndexByNthList
    -215      * @memberOf ASN1HEX
    -216      * @function
    -217      * @param {String} h hexadecimal string of ASN.1 DER encoded data
    -218      * @param {Number} currentIndex start string index of ASN.1 object
    -219      * @param {Array of Number} nthList array list of nth
    -220      * @return {Number} string index refered by nthList
    -221      * @since 1.1
    -222      * @example
    -223      * The "nthList" is a index list of structured ASN.1 object
    -224      * reference. Here is a sample structure and "nthList"s which
    -225      * refers each objects.
    -226      *
    -227      * SQUENCE               - 
    -228      *   SEQUENCE            - [0]
    -229      *     IA5STRING 000     - [0, 0]
    -230      *     UTF8STRING 001    - [0, 1]
    -231      *   SET                 - [1]
    -232      *     IA5STRING 010     - [1, 0]
    -233      *     UTF8STRING 011    - [1, 1]
    -234      */
    -235     this.getDecendantIndexByNthList = function(h, currentIndex, nthList) {
    -236         if (nthList.length == 0) {
    -237             return currentIndex;
    -238         }
    -239         var firstNth = nthList.shift();
    -240         var a = this.getPosArrayOfChildren_AtObj(h, currentIndex);
    -241         return this.getDecendantIndexByNthList(h, a[firstNth], nthList);
    -242     };
    -243 
    -244     /**
    -245      * get hexadecimal string of ASN.1 TLV refered by current index and nth index list.
    -246      * @name getDecendantHexTLVByNthList
    -247      * @memberOf ASN1HEX
    -248      * @function
    -249      * @param {String} h hexadecimal string of ASN.1 DER encoded data
    -250      * @param {Number} currentIndex start string index of ASN.1 object
    -251      * @param {Array of Number} nthList array list of nth
    -252      * @return {Number} hexadecimal string of ASN.1 TLV refered by nthList
    -253      * @since 1.1
    -254      */
    -255     this.getDecendantHexTLVByNthList = function(h, currentIndex, nthList) {
    -256         var idx = this.getDecendantIndexByNthList(h, currentIndex, nthList);
    -257         return this.getHexOfTLV_AtObj(h, idx);
    -258     };
    -259 
    -260     /**
    -261      * get hexadecimal string of ASN.1 V refered by current index and nth index list.
    -262      * @name getDecendantHexVByNthList
    -263      * @memberOf ASN1HEX
    -264      * @function
    -265      * @param {String} h hexadecimal string of ASN.1 DER encoded data
    -266      * @param {Number} currentIndex start string index of ASN.1 object
    -267      * @param {Array of Number} nthList array list of nth
    -268      * @return {Number} hexadecimal string of ASN.1 V refered by nthList
    -269      * @since 1.1
    + 41  * @description
    + 42  * This class provides a parser for hexadecimal string of
    + 43  * DER encoded ASN.1 binary data.
    + 44  * Here are major methods of this class.
    + 45  * <ul>
    + 46  * <li><b>ACCESS BY POSITION</b>
    + 47  *   <ul>
    + 48  *   <li>{@link ASN1HEX.getHexOfTLV_AtObj} - get ASN.1 TLV at specified position</li>
    + 49  *   <li>{@link ASN1HEX.getHexOfV_AtObj} - get ASN.1 V at specified position</li>
    + 50  *   <li>{@link ASN1HEX.getHexOfL_AtObj} - get hexadecimal ASN.1 L at specified position</li>
    + 51  *   <li>{@link ASN1HEX.getIntOfL_AtObj} - get integer ASN.1 L at specified position</li>
    + 52  *   <li>{@link ASN1HEX.getStartPosOfV_AtObj} - get ASN.1 V position from its ASN.1 TLV position</li>
    + 53  *   </ul>
    + 54  * </li>
    + 55  * <li><b>ACCESS FOR CHILD ITEM</b>
    + 56  *   <ul>
    + 57  *   <li>{@link ASN1HEX.getNthChildIndex_AtObj} - get nth child index at specified position</li>
    + 58  *   <li>{@link ASN1HEX.getPosArrayOfChildren_AtObj} - get indexes of children</li>
    + 59  *   <li>{@link ASN1HEX.getPosOfNextSibling_AtObj} - get position of next sibling</li>
    + 60  *   </ul>
    + 61  * </li>
    + 62  * <li><b>ACCESS NESTED ASN.1 STRUCTURE</b>
    + 63  *   <ul>
    + 64  *   <li>{@link ASN1HEX.getDecendantHexTLVByNthList} - get ASN.1 TLV at specified list index</li>
    + 65  *   <li>{@link ASN1HEX.getDecendantHexVByNthList} - get ASN.1 V at specified list index</li>
    + 66  *   <li>{@link ASN1HEX.getDecendantIndexByNthList} - get index at specified list index</li>
    + 67  *   </ul>
    + 68  * </li>
    + 69  * <li><b>UTILITIES</b>
    + 70  *   <ul>
    + 71  *   <li>{@link ASN1HEX.dump} - dump ASN.1 structure</li>
    + 72  *   <li>{@link ASN1HEX.isASN1HEX} - check whether ASN.1 hexadecimal string or not</li>
    + 73  *   <li>{@link ASN1HEX.hextooidstr} - convert hexadecimal string of OID to dotted integer list</li>
    + 74  *   </ul>
    + 75  * </li>
    + 76  * </ul>
    + 77  */
    + 78 var ASN1HEX = new function() {
    + 79     /**
    + 80      * get byte length for ASN.1 L(length) bytes
    + 81      * @name getByteLengthOfL_AtObj
    + 82      * @memberOf ASN1HEX
    + 83      * @function
    + 84      * @param {String} s hexadecimal string of ASN.1 DER encoded data
    + 85      * @param {Number} pos string index
    + 86      * @return byte length for ASN.1 L(length) bytes
    + 87      */
    + 88     this.getByteLengthOfL_AtObj = function(s, pos) {
    + 89         if (s.substring(pos + 2, pos + 3) != '8') return 1;
    + 90         var i = parseInt(s.substring(pos + 3, pos + 4));
    + 91         if (i == 0) return -1;          // length octet '80' indefinite length
    + 92         if (0 < i && i < 10) return i + 1;      // including '8?' octet;
    + 93         return -2;                              // malformed format
    + 94     };
    + 95 
    + 96     /**
    + 97      * get hexadecimal string for ASN.1 L(length) bytes
    + 98      * @name getHexOfL_AtObj
    + 99      * @memberOf ASN1HEX
    +100      * @function
    +101      * @param {String} s hexadecimal string of ASN.1 DER encoded data
    +102      * @param {Number} pos string index
    +103      * @return {String} hexadecimal string for ASN.1 L(length) bytes
    +104      */
    +105     this.getHexOfL_AtObj = function(s, pos) {
    +106         var len = this.getByteLengthOfL_AtObj(s, pos);
    +107         if (len < 1) return '';
    +108         return s.substring(pos + 2, pos + 2 + len * 2);
    +109     };
    +110 
    +111     //   getting ASN.1 length value at the position 'idx' of
    +112     //   hexa decimal string 's'.
    +113     //
    +114     //   f('3082025b02...', 0) ... 82025b ... ???
    +115     //   f('020100', 0) ... 01 ... 1
    +116     //   f('0203001...', 0) ... 03 ... 3
    +117     //   f('02818003...', 0) ... 8180 ... 128
    +118     /**
    +119      * get integer value of ASN.1 length for ASN.1 data
    +120      * @name getIntOfL_AtObj
    +121      * @memberOf ASN1HEX
    +122      * @function
    +123      * @param {String} s hexadecimal string of ASN.1 DER encoded data
    +124      * @param {Number} pos string index
    +125      * @return ASN.1 L(length) integer value
    +126      */
    +127     this.getIntOfL_AtObj = function(s, pos) {
    +128         var hLength = this.getHexOfL_AtObj(s, pos);
    +129         if (hLength == '') return -1;
    +130         var bi;
    +131         if (parseInt(hLength.substring(0, 1)) < 8) {
    +132             bi = new BigInteger(hLength, 16);
    +133         } else {
    +134             bi = new BigInteger(hLength.substring(2), 16);
    +135         }
    +136         return bi.intValue();
    +137     };
    +138 
    +139     /**
    +140      * get ASN.1 value starting string position for ASN.1 object refered by index 'idx'.
    +141      * @name getStartPosOfV_AtObj
    +142      * @memberOf ASN1HEX
    +143      * @function
    +144      * @param {String} s hexadecimal string of ASN.1 DER encoded data
    +145      * @param {Number} pos string index
    +146      */
    +147     this.getStartPosOfV_AtObj = function(s, pos) {
    +148         var l_len = this.getByteLengthOfL_AtObj(s, pos);
    +149         if (l_len < 0) return l_len;
    +150         return pos + (l_len + 1) * 2;
    +151     };
    +152 
    +153     /**
    +154      * get hexadecimal string of ASN.1 V(value)
    +155      * @name getHexOfV_AtObj
    +156      * @memberOf ASN1HEX
    +157      * @function
    +158      * @param {String} s hexadecimal string of ASN.1 DER encoded data
    +159      * @param {Number} pos string index
    +160      * @return {String} hexadecimal string of ASN.1 value.
    +161      */
    +162     this.getHexOfV_AtObj = function(s, pos) {
    +163         var pos1 = this.getStartPosOfV_AtObj(s, pos);
    +164         var len = this.getIntOfL_AtObj(s, pos);
    +165         return s.substring(pos1, pos1 + len * 2);
    +166     };
    +167 
    +168     /**
    +169      * get hexadecimal string of ASN.1 TLV at
    +170      * @name getHexOfTLV_AtObj
    +171      * @memberOf ASN1HEX
    +172      * @function
    +173      * @param {String} s hexadecimal string of ASN.1 DER encoded data
    +174      * @param {Number} pos string index
    +175      * @return {String} hexadecimal string of ASN.1 TLV.
    +176      * @since 1.1
    +177      */
    +178     this.getHexOfTLV_AtObj = function(s, pos) {
    +179         var hT = s.substr(pos, 2);
    +180         var hL = this.getHexOfL_AtObj(s, pos);
    +181         var hV = this.getHexOfV_AtObj(s, pos);
    +182         return hT + hL + hV;
    +183     };
    +184 
    +185     /**
    +186      * get next sibling starting index for ASN.1 object string
    +187      * @name getPosOfNextSibling_AtObj
    +188      * @memberOf ASN1HEX
    +189      * @function
    +190      * @param {String} s hexadecimal string of ASN.1 DER encoded data
    +191      * @param {Number} pos string index
    +192      * @return next sibling starting index for ASN.1 object string
    +193      */
    +194     this.getPosOfNextSibling_AtObj = function(s, pos) {
    +195         var pos1 = this.getStartPosOfV_AtObj(s, pos);
    +196         var len = this.getIntOfL_AtObj(s, pos);
    +197         return pos1 + len * 2;
    +198     };
    +199 
    +200     /**
    +201      * get array of indexes of child ASN.1 objects
    +202      * @name getPosArrayOfChildren_AtObj
    +203      * @memberOf ASN1HEX
    +204      * @function
    +205      * @param {String} s hexadecimal string of ASN.1 DER encoded data
    +206      * @param {Number} start string index of ASN.1 object
    +207      * @return {Array of Number} array of indexes for childen of ASN.1 objects
    +208      */
    +209     this.getPosArrayOfChildren_AtObj = function(h, pos) {
    +210         var a = new Array();
    +211         var p0 = this.getStartPosOfV_AtObj(h, pos);
    +212         a.push(p0);
    +213 
    +214         var len = this.getIntOfL_AtObj(h, pos);
    +215         var p = p0;
    +216         var k = 0;
    +217         while (1) {
    +218             var pNext = this.getPosOfNextSibling_AtObj(h, p);
    +219             if (pNext == null || (pNext - p0  >= (len * 2))) break;
    +220             if (k >= 200) break;
    +221             
    +222             a.push(pNext);
    +223             p = pNext;
    +224             
    +225             k++;
    +226         }
    +227         
    +228         return a;
    +229     };
    +230 
    +231     /**
    +232      * get string index of nth child object of ASN.1 object refered by h, idx
    +233      * @name getNthChildIndex_AtObj
    +234      * @memberOf ASN1HEX
    +235      * @function
    +236      * @param {String} h hexadecimal string of ASN.1 DER encoded data
    +237      * @param {Number} idx start string index of ASN.1 object
    +238      * @param {Number} nth for child
    +239      * @return {Number} string index of nth child.
    +240      * @since 1.1
    +241      */
    +242     this.getNthChildIndex_AtObj = function(h, idx, nth) {
    +243         var a = this.getPosArrayOfChildren_AtObj(h, idx);
    +244         return a[nth];
    +245     };
    +246 
    +247     // ========== decendant methods ==============================
    +248     /**
    +249      * get string index of nth child object of ASN.1 object refered by h, idx
    +250      * @name getDecendantIndexByNthList
    +251      * @memberOf ASN1HEX
    +252      * @function
    +253      * @param {String} h hexadecimal string of ASN.1 DER encoded data
    +254      * @param {Number} currentIndex start string index of ASN.1 object
    +255      * @param {Array of Number} nthList array list of nth
    +256      * @return {Number} string index refered by nthList
    +257      * @since 1.1
    +258      * @example
    +259      * The "nthList" is a index list of structured ASN.1 object
    +260      * reference. Here is a sample structure and "nthList"s which
    +261      * refers each objects.
    +262      *
    +263      * SQUENCE               - 
    +264      *   SEQUENCE            - [0]
    +265      *     IA5STRING 000     - [0, 0]
    +266      *     UTF8STRING 001    - [0, 1]
    +267      *   SET                 - [1]
    +268      *     IA5STRING 010     - [1, 0]
    +269      *     UTF8STRING 011    - [1, 1]
     270      */
    -271     this.getDecendantHexVByNthList = function(h, currentIndex, nthList) {
    -272         var idx = this.getDecendantIndexByNthList(h, currentIndex, nthList);
    -273         return this.getHexOfV_AtObj(h, idx);
    -274     };
    -275 };
    -276 
    -277 /*
    -278  * @since asn1hex 1.1.4
    -279  */
    -280 ASN1HEX.getVbyList = function(h, currentIndex, nthList, checkingTag) {
    -281     var idx = this.getDecendantIndexByNthList(h, currentIndex, nthList);
    -282     if (idx === undefined) {
    -283         throw "can't find nthList object";
    -284     }
    -285     if (checkingTag !== undefined) {
    -286         if (h.substr(idx, 2) != checkingTag) {
    -287             throw "checking tag doesn't match: " + 
    -288                 h.substr(idx,2) + "!=" + checkingTag;
    -289         }
    -290     }
    -291     return this.getHexOfV_AtObj(h, idx);
    -292 };
    -293 
    -294 /**
    -295  * get OID string from hexadecimal encoded value
    -296  * @name hextooidstr
    -297  * @memberOf ASN1HEX
    -298  * @function
    -299  * @param {String} hex hexadecmal string of ASN.1 DER encoded OID value
    -300  * @return {String} OID string (ex. '1.2.3.4.567')
    -301  * @since asn1hex 1.1.5
    -302  */
    -303 ASN1HEX.hextooidstr = function(hex) {
    -304     var zeroPadding = function(s, len) {
    -305         if (s.length >= len) return s;
    -306         return new Array(len - s.length + 1).join('0') + s;
    -307     };
    -308 
    -309     var a = [];
    -310 
    -311     // a[0], a[1]
    -312     var hex0 = hex.substr(0, 2);
    -313     var i0 = parseInt(hex0, 16);
    -314     a[0] = new String(Math.floor(i0 / 40));
    -315     a[1] = new String(i0 % 40);
    -316 
    -317     // a[2]..a[n]
    -318    var hex1 = hex.substr(2);
    -319     var b = [];
    -320     for (var i = 0; i < hex1.length / 2; i++) {
    -321     b.push(parseInt(hex1.substr(i * 2, 2), 16));
    -322     }
    -323     var c = [];
    -324     var cbin = "";
    -325     for (var i = 0; i < b.length; i++) {
    -326         if (b[i] & 0x80) {
    -327             cbin = cbin + zeroPadding((b[i] & 0x7f).toString(2), 7);
    -328         } else {
    -329             cbin = cbin + zeroPadding((b[i] & 0x7f).toString(2), 7);
    -330             c.push(new String(parseInt(cbin, 2)));
    -331             cbin = "";
    -332         }
    -333     }
    -334 
    -335     var s = a.join(".");
    -336     if (c.length > 0) s = s + "." + c.join(".");
    -337     return s;
    -338 };
    -339 
    -340 /**
    -341  * get string of simple ASN.1 dump from hexadecimal ASN.1 data
    -342  * @name dump
    -343  * @memberOf ASN1HEX
    -344  * @function
    -345  * @param {String} hex hexadecmal string of ASN.1 data
    -346  * @param {Array} associative array of flags for dump (OPTION)
    -347  * @param {Number} idx string index for starting dump (OPTION)
    -348  * @param {String} indent string (OPTION)
    -349  * @return {String} string of simple ASN.1 dump
    -350  * @since jsrsasign 4.8.3 asn1hex 1.1.6
    -351  * @description
    -352  * This method will get an ASN.1 dump from
    -353  * hexadecmal string of ASN.1 DER encoded data.
    -354  * Here are features:
    -355  * <ul>
    -356  * <li>ommit long hexadecimal string</li>
    -357  * <li>dump encapsulated OCTET STRING (good for X.509v3 extensions)</li>
    -358  * <li>structured/primitive context specific tag support (i.e. [0], [3] ...)</li>
    -359  * <li>automatic decode for implicit primitive context specific tag 
    -360  * (good for X.509v3 extension value)
    -361  *   <ul>
    -362  *   <li>if hex starts '68747470'(i.e. http) it is decoded as utf8 encoded string.</li>
    -363  *   <li>if it is in 'subjectAltName' extension value and is '[2]'(dNSName) tag
    -364  *   value will be encoded as utf8 string</li>
    -365  *   <li>otherwise it shows as hexadecimal string</li>
    -366  *   </ul>
    -367  * </li>
    -368  * </ul>
    -369  * @example
    -370  * // ASN.1 INTEGER
    -371  * ASN1HEX.dump('0203012345')
    -372  * ↓
    -373  * INTEGER 012345
    -374  * // ASN.1 Object Identifier
    -375  * ASN1HEX.dump('06052b0e03021a')
    -376  * ↓
    -377  * ObjectIdentifier sha1 (1 3 14 3 2 26)
    -378  * // ASN.1 SEQUENCE
    -379  * ASN1HEX.dump('3006020101020102')
    -380  * ↓
    -381  * SEQUENCE
    -382  *   INTEGER 01
    -383  *   INTEGER 02
    -384  * // ASN.1 DUMP FOR X.509 CERTIFICATE
    -385  * ASN1HEX.dump(X509.pemToHex(certPEM))
    -386  * ↓
    -387  * SEQUENCE
    -388  *   SEQUENCE
    -389  *     [0]
    -390  *       INTEGER 02
    -391  *     INTEGER 0c009310d206dbe337553580118ddc87
    -392  *     SEQUENCE
    -393  *       ObjectIdentifier SHA256withRSA (1 2 840 113549 1 1 11)
    -394  *       NULL
    -395  *     SEQUENCE
    -396  *       SET
    -397  *         SEQUENCE
    -398  *           ObjectIdentifier countryName (2 5 4 6)
    -399  *           PrintableString 'US'
    -400  *             :
    -401  */
    -402 ASN1HEX.dump = function(hex, flags, idx, indent) {
    -403     var _skipLongHex = function(hex, limitNumOctet) {
    -404 	if (hex.length <= limitNumOctet * 2) {
    -405 	    return hex;
    -406 	} else {
    -407 	    var s = hex.substr(0, limitNumOctet) + 
    -408 		    "..(total " + hex.length / 2 + "bytes).." +
    -409 		    hex.substr(hex.length - limitNumOctet, limitNumOctet);
    -410 	    return s;
    -411 	};
    -412     };
    -413 
    -414     if (flags === undefined) flags = { "ommit_long_octet": 32 };
    -415     if (idx === undefined) idx = 0;
    -416     if (indent === undefined) indent = "";
    -417     var skipLongHex = flags.ommit_long_octet;
    -418 
    -419     if (hex.substr(idx, 2) == "01") {
    -420 	var v = ASN1HEX.getHexOfV_AtObj(hex, idx);
    -421 	if (v == "00") {
    -422 	    return indent + "BOOLEAN FALSE\n";
    -423 	} else {
    -424 	    return indent + "BOOLEAN TRUE\n";
    -425 	}
    -426     }
    -427     if (hex.substr(idx, 2) == "02") {
    -428 	var v = ASN1HEX.getHexOfV_AtObj(hex, idx);
    -429 	return indent + "INTEGER " + _skipLongHex(v, skipLongHex) + "\n";
    -430     }
    -431     if (hex.substr(idx, 2) == "03") {
    -432 	var v = ASN1HEX.getHexOfV_AtObj(hex, idx);
    -433 	return indent + "BITSTRING " + _skipLongHex(v, skipLongHex) + "\n";
    -434     }
    -435     if (hex.substr(idx, 2) == "04") {
    -436 	var v = ASN1HEX.getHexOfV_AtObj(hex, idx);
    -437 	if (ASN1HEX.isASN1HEX(v)) {
    -438 	    var s = indent + "OCTETSTRING, encapsulates\n";
    -439 	    s = s + ASN1HEX.dump(v, flags, 0, indent + "  ");
    -440 	    return s;
    -441 	} else {
    -442 	    return indent + "OCTETSTRING " + _skipLongHex(v, skipLongHex) + "\n";
    -443 	}
    -444     }
    -445     if (hex.substr(idx, 2) == "05") {
    -446 	return indent + "NULL\n";
    -447     }
    -448     if (hex.substr(idx, 2) == "06") {
    -449 	var hV = ASN1HEX.getHexOfV_AtObj(hex, idx);
    -450         var oidDot = KJUR.asn1.ASN1Util.oidHexToInt(hV);
    -451         var oidName = KJUR.asn1.x509.OID.oid2name(oidDot);
    -452 	var oidSpc = oidDot.replace(/\./g, ' ');
    -453         if (oidName != '') {
    -454   	    return indent + "ObjectIdentifier " + oidName + " (" + oidSpc + ")\n";
    -455 	} else {
    -456   	    return indent + "ObjectIdentifier (" + oidSpc + ")\n";
    -457 	}
    -458     }
    -459     if (hex.substr(idx, 2) == "0c") {
    -460 	return indent + "UTF8String '" + hextoutf8(ASN1HEX.getHexOfV_AtObj(hex, idx)) + "'\n";
    -461     }
    -462     if (hex.substr(idx, 2) == "13") {
    -463 	return indent + "PrintableString '" + hextoutf8(ASN1HEX.getHexOfV_AtObj(hex, idx)) + "'\n";
    -464     }
    -465     if (hex.substr(idx, 2) == "14") {
    -466 	return indent + "TeletexString '" + hextoutf8(ASN1HEX.getHexOfV_AtObj(hex, idx)) + "'\n";
    -467     }
    -468     if (hex.substr(idx, 2) == "16") {
    -469 	return indent + "IA5String '" + hextoutf8(ASN1HEX.getHexOfV_AtObj(hex, idx)) + "'\n";
    -470     }
    -471     if (hex.substr(idx, 2) == "17") {
    -472 	return indent + "UTCTime " + hextoutf8(ASN1HEX.getHexOfV_AtObj(hex, idx)) + "\n";
    +271     this.getDecendantIndexByNthList = function(h, currentIndex, nthList) {
    +272         if (nthList.length == 0) {
    +273             return currentIndex;
    +274         }
    +275         var firstNth = nthList.shift();
    +276         var a = this.getPosArrayOfChildren_AtObj(h, currentIndex);
    +277         return this.getDecendantIndexByNthList(h, a[firstNth], nthList);
    +278     };
    +279 
    +280     /**
    +281      * get hexadecimal string of ASN.1 TLV refered by current index and nth index list.
    +282      * @name getDecendantHexTLVByNthList
    +283      * @memberOf ASN1HEX
    +284      * @function
    +285      * @param {String} h hexadecimal string of ASN.1 DER encoded data
    +286      * @param {Number} currentIndex start string index of ASN.1 object
    +287      * @param {Array of Number} nthList array list of nth
    +288      * @return {Number} hexadecimal string of ASN.1 TLV refered by nthList
    +289      * @since 1.1
    +290      */
    +291     this.getDecendantHexTLVByNthList = function(h, currentIndex, nthList) {
    +292         var idx = this.getDecendantIndexByNthList(h, currentIndex, nthList);
    +293         return this.getHexOfTLV_AtObj(h, idx);
    +294     };
    +295 
    +296     /**
    +297      * get hexadecimal string of ASN.1 V refered by current index and nth index list.
    +298      * @name getDecendantHexVByNthList
    +299      * @memberOf ASN1HEX
    +300      * @function
    +301      * @param {String} h hexadecimal string of ASN.1 DER encoded data
    +302      * @param {Number} currentIndex start string index of ASN.1 object
    +303      * @param {Array of Number} nthList array list of nth
    +304      * @return {Number} hexadecimal string of ASN.1 V refered by nthList
    +305      * @since 1.1
    +306      */
    +307     this.getDecendantHexVByNthList = function(h, currentIndex, nthList) {
    +308         var idx = this.getDecendantIndexByNthList(h, currentIndex, nthList);
    +309         return this.getHexOfV_AtObj(h, idx);
    +310     };
    +311 };
    +312 
    +313 /*
    +314  * @since asn1hex 1.1.4
    +315  */
    +316 ASN1HEX.getVbyList = function(h, currentIndex, nthList, checkingTag) {
    +317     var idx = this.getDecendantIndexByNthList(h, currentIndex, nthList);
    +318     if (idx === undefined) {
    +319         throw "can't find nthList object";
    +320     }
    +321     if (checkingTag !== undefined) {
    +322         if (h.substr(idx, 2) != checkingTag) {
    +323             throw "checking tag doesn't match: " + 
    +324                 h.substr(idx,2) + "!=" + checkingTag;
    +325         }
    +326     }
    +327     return this.getHexOfV_AtObj(h, idx);
    +328 };
    +329 
    +330 /**
    +331  * get OID string from hexadecimal encoded value
    +332  * @name hextooidstr
    +333  * @memberOf ASN1HEX
    +334  * @function
    +335  * @param {String} hex hexadecmal string of ASN.1 DER encoded OID value
    +336  * @return {String} OID string (ex. '1.2.3.4.567')
    +337  * @since asn1hex 1.1.5
    +338  */
    +339 ASN1HEX.hextooidstr = function(hex) {
    +340     var zeroPadding = function(s, len) {
    +341         if (s.length >= len) return s;
    +342         return new Array(len - s.length + 1).join('0') + s;
    +343     };
    +344 
    +345     var a = [];
    +346 
    +347     // a[0], a[1]
    +348     var hex0 = hex.substr(0, 2);
    +349     var i0 = parseInt(hex0, 16);
    +350     a[0] = new String(Math.floor(i0 / 40));
    +351     a[1] = new String(i0 % 40);
    +352 
    +353     // a[2]..a[n]
    +354    var hex1 = hex.substr(2);
    +355     var b = [];
    +356     for (var i = 0; i < hex1.length / 2; i++) {
    +357     b.push(parseInt(hex1.substr(i * 2, 2), 16));
    +358     }
    +359     var c = [];
    +360     var cbin = "";
    +361     for (var i = 0; i < b.length; i++) {
    +362         if (b[i] & 0x80) {
    +363             cbin = cbin + zeroPadding((b[i] & 0x7f).toString(2), 7);
    +364         } else {
    +365             cbin = cbin + zeroPadding((b[i] & 0x7f).toString(2), 7);
    +366             c.push(new String(parseInt(cbin, 2)));
    +367             cbin = "";
    +368         }
    +369     }
    +370 
    +371     var s = a.join(".");
    +372     if (c.length > 0) s = s + "." + c.join(".");
    +373     return s;
    +374 };
    +375 
    +376 /**
    +377  * get string of simple ASN.1 dump from hexadecimal ASN.1 data
    +378  * @name dump
    +379  * @memberOf ASN1HEX
    +380  * @function
    +381  * @param {String} hex hexadecmal string of ASN.1 data
    +382  * @param {Array} associative array of flags for dump (OPTION)
    +383  * @param {Number} idx string index for starting dump (OPTION)
    +384  * @param {String} indent string (OPTION)
    +385  * @return {String} string of simple ASN.1 dump
    +386  * @since jsrsasign 4.8.3 asn1hex 1.1.6
    +387  * @description
    +388  * This method will get an ASN.1 dump from
    +389  * hexadecmal string of ASN.1 DER encoded data.
    +390  * Here are features:
    +391  * <ul>
    +392  * <li>ommit long hexadecimal string</li>
    +393  * <li>dump encapsulated OCTET STRING (good for X.509v3 extensions)</li>
    +394  * <li>structured/primitive context specific tag support (i.e. [0], [3] ...)</li>
    +395  * <li>automatic decode for implicit primitive context specific tag 
    +396  * (good for X.509v3 extension value)
    +397  *   <ul>
    +398  *   <li>if hex starts '68747470'(i.e. http) it is decoded as utf8 encoded string.</li>
    +399  *   <li>if it is in 'subjectAltName' extension value and is '[2]'(dNSName) tag
    +400  *   value will be encoded as utf8 string</li>
    +401  *   <li>otherwise it shows as hexadecimal string</li>
    +402  *   </ul>
    +403  * </li>
    +404  * </ul>
    +405  * @example
    +406  * // ASN.1 INTEGER
    +407  * ASN1HEX.dump('0203012345')
    +408  * ↓
    +409  * INTEGER 012345
    +410  *
    +411  * // ASN.1 Object Identifier
    +412  * ASN1HEX.dump('06052b0e03021a')
    +413  * ↓
    +414  * ObjectIdentifier sha1 (1 3 14 3 2 26)
    +415  *
    +416  * // ASN.1 SEQUENCE
    +417  * ASN1HEX.dump('3006020101020102')
    +418  * ↓
    +419  * SEQUENCE
    +420  *   INTEGER 01
    +421  *   INTEGER 02
    +422  *
    +423  * // ASN.1 DUMP FOR X.509 CERTIFICATE
    +424  * ASN1HEX.dump(X509.pemToHex(certPEM))
    +425  * ↓
    +426  * SEQUENCE
    +427  *   SEQUENCE
    +428  *     [0]
    +429  *       INTEGER 02
    +430  *     INTEGER 0c009310d206dbe337553580118ddc87
    +431  *     SEQUENCE
    +432  *       ObjectIdentifier SHA256withRSA (1 2 840 113549 1 1 11)
    +433  *       NULL
    +434  *     SEQUENCE
    +435  *       SET
    +436  *         SEQUENCE
    +437  *           ObjectIdentifier countryName (2 5 4 6)
    +438  *           PrintableString 'US'
    +439  *             :
    +440  */
    +441 ASN1HEX.dump = function(hex, flags, idx, indent) {
    +442     var _skipLongHex = function(hex, limitNumOctet) {
    +443 	if (hex.length <= limitNumOctet * 2) {
    +444 	    return hex;
    +445 	} else {
    +446 	    var s = hex.substr(0, limitNumOctet) + 
    +447 		    "..(total " + hex.length / 2 + "bytes).." +
    +448 		    hex.substr(hex.length - limitNumOctet, limitNumOctet);
    +449 	    return s;
    +450 	};
    +451     };
    +452 
    +453     if (flags === undefined) flags = { "ommit_long_octet": 32 };
    +454     if (idx === undefined) idx = 0;
    +455     if (indent === undefined) indent = "";
    +456     var skipLongHex = flags.ommit_long_octet;
    +457 
    +458     if (hex.substr(idx, 2) == "01") {
    +459 	var v = ASN1HEX.getHexOfV_AtObj(hex, idx);
    +460 	if (v == "00") {
    +461 	    return indent + "BOOLEAN FALSE\n";
    +462 	} else {
    +463 	    return indent + "BOOLEAN TRUE\n";
    +464 	}
    +465     }
    +466     if (hex.substr(idx, 2) == "02") {
    +467 	var v = ASN1HEX.getHexOfV_AtObj(hex, idx);
    +468 	return indent + "INTEGER " + _skipLongHex(v, skipLongHex) + "\n";
    +469     }
    +470     if (hex.substr(idx, 2) == "03") {
    +471 	var v = ASN1HEX.getHexOfV_AtObj(hex, idx);
    +472 	return indent + "BITSTRING " + _skipLongHex(v, skipLongHex) + "\n";
     473     }
    -474     if (hex.substr(idx, 2) == "18") {
    -475 	return indent + "GeneralizedTime " + hextoutf8(ASN1HEX.getHexOfV_AtObj(hex, idx)) + "\n";
    -476     }
    -477     if (hex.substr(idx, 2) == "30") {
    -478 	if (hex.substr(idx, 4) == "3000") {
    -479 	    return indent + "SEQUENCE {}\n";
    -480 	}
    -481 
    -482 	var s = indent + "SEQUENCE\n";
    -483 	var aIdx = ASN1HEX.getPosArrayOfChildren_AtObj(hex, idx);
    -484 
    -485 	var flagsTemp = flags;
    -486 	
    -487 	if ((aIdx.length == 2 || aIdx.length == 3) &&
    -488 	    hex.substr(aIdx[0], 2) == "06" &&
    -489 	    hex.substr(aIdx[aIdx.length - 1], 2) == "04") { // supposed X.509v3 extension
    -490 	    var oidHex = ASN1HEX.getHexOfV_AtObj(hex, aIdx[0]);
    -491 	    var oidDot = KJUR.asn1.ASN1Util.oidHexToInt(oidHex);
    -492 	    var oidName = KJUR.asn1.x509.OID.oid2name(oidDot);
    -493 
    -494 	    var flagsClone = JSON.parse(JSON.stringify(flags));
    -495 	    flagsClone.x509ExtName = oidName;
    -496 	    flagsTemp = flagsClone;
    -497 	}
    -498 	
    -499 	for (var i = 0; i < aIdx.length; i++) {
    -500 	    s = s + ASN1HEX.dump(hex, flagsTemp, aIdx[i], indent + "  ");
    -501 	}
    -502 	return s;
    +474     if (hex.substr(idx, 2) == "04") {
    +475 	var v = ASN1HEX.getHexOfV_AtObj(hex, idx);
    +476 	if (ASN1HEX.isASN1HEX(v)) {
    +477 	    var s = indent + "OCTETSTRING, encapsulates\n";
    +478 	    s = s + ASN1HEX.dump(v, flags, 0, indent + "  ");
    +479 	    return s;
    +480 	} else {
    +481 	    return indent + "OCTETSTRING " + _skipLongHex(v, skipLongHex) + "\n";
    +482 	}
    +483     }
    +484     if (hex.substr(idx, 2) == "05") {
    +485 	return indent + "NULL\n";
    +486     }
    +487     if (hex.substr(idx, 2) == "06") {
    +488 	var hV = ASN1HEX.getHexOfV_AtObj(hex, idx);
    +489         var oidDot = KJUR.asn1.ASN1Util.oidHexToInt(hV);
    +490         var oidName = KJUR.asn1.x509.OID.oid2name(oidDot);
    +491 	var oidSpc = oidDot.replace(/\./g, ' ');
    +492         if (oidName != '') {
    +493   	    return indent + "ObjectIdentifier " + oidName + " (" + oidSpc + ")\n";
    +494 	} else {
    +495   	    return indent + "ObjectIdentifier (" + oidSpc + ")\n";
    +496 	}
    +497     }
    +498     if (hex.substr(idx, 2) == "0c") {
    +499 	return indent + "UTF8String '" + hextoutf8(ASN1HEX.getHexOfV_AtObj(hex, idx)) + "'\n";
    +500     }
    +501     if (hex.substr(idx, 2) == "13") {
    +502 	return indent + "PrintableString '" + hextoutf8(ASN1HEX.getHexOfV_AtObj(hex, idx)) + "'\n";
     503     }
    -504     if (hex.substr(idx, 2) == "31") {
    -505 	var s = indent + "SET\n";
    -506 	var aIdx = ASN1HEX.getPosArrayOfChildren_AtObj(hex, idx);
    -507 	for (var i = 0; i < aIdx.length; i++) {
    -508 	    s = s + ASN1HEX.dump(hex, flags, aIdx[i], indent + "  ");
    -509 	}
    -510 	return s;
    -511     }
    -512     var tag = parseInt(hex.substr(idx, 2), 16);
    -513     if ((tag & 128) != 0) { // context specific 
    -514 	var tagNumber = tag & 31;
    -515 	if ((tag & 32) != 0) { // structured tag
    -516 	    var s = indent + "[" + tagNumber + "]\n";
    -517 	    var aIdx = ASN1HEX.getPosArrayOfChildren_AtObj(hex, idx);
    -518 	    for (var i = 0; i < aIdx.length; i++) {
    -519 		s = s + ASN1HEX.dump(hex, flags, aIdx[i], indent + "  ");
    -520 	    }
    -521 	    return s;
    -522 	} else { // primitive tag
    -523 	    var v = ASN1HEX.getHexOfV_AtObj(hex, idx);
    -524 	    if (v.substr(0, 8) == "68747470") { // http
    -525 		v = hextoutf8(v);
    -526 	    }
    -527 	    if (flags.x509ExtName === "subjectAltName" &&
    -528 		tagNumber == 2) {
    -529 		v = hextoutf8(v);
    -530 	    }
    -531 	    
    -532 	    var s = indent + "[" + tagNumber + "] " + v + "\n";
    -533 	    return s;
    -534 	}
    -535     }
    -536     return indent + "UNKNOWN(" + hex.substr(idx, 2) + ") " + ASN1HEX.getHexOfV_AtObj(hex, idx) + "\n";
    -537 };
    -538 
    -539 /**
    -540  * check wheather the string is ASN.1 hexadecimal string or not
    -541  * @name isASN1HEX
    -542  * @memberOf ASN1HEX
    -543  * @function
    -544  * @param {String} hex string to check whether it is hexadecmal string for ASN.1 DER or not
    -545  * @return {Boolean} true if it is hexadecimal string of ASN.1 data otherwise false
    -546  * @since jsrsasign 4.8.3 asn1hex 1.1.6
    -547  * @description
    -548  * This method checks wheather the argument 'hex' is a hexadecimal string of
    -549  * ASN.1 data or not.
    -550  * @example
    -551  * ASN1HEX.isASN1HEX('0203012345') → true // PROPER ASN.1 INTEGER
    -552  * ASN1HEX.isASN1HEX('0203012345ff') → false // TOO LONG VALUE
    -553  * ASN1HEX.isASN1HEX('02030123') → false // TOO SHORT VALUE
    -554  * ASN1HEX.isASN1HEX('fa3bcd') → false // WRONG FOR ASN.1
    -555  */
    -556 ASN1HEX.isASN1HEX = function(hex) {
    -557     if (hex.length % 2 == 1) return false;
    -558 
    -559     var intL = ASN1HEX.getIntOfL_AtObj(hex, 0);
    -560     var tV = hex.substr(0, 2);
    -561     var lV = ASN1HEX.getHexOfL_AtObj(hex, 0);
    -562     var hVLength = hex.length - tV.length - lV.length;
    -563     if (hVLength == intL * 2) return true;
    -564 
    -565     return false;
    -566 };
    -567 
    \ No newline at end of file +504
    if (hex.substr(idx, 2) == "14") { +505 return indent + "TeletexString '" + hextoutf8(ASN1HEX.getHexOfV_AtObj(hex, idx)) + "'\n"; +506 } +507 if (hex.substr(idx, 2) == "16") { +508 return indent + "IA5String '" + hextoutf8(ASN1HEX.getHexOfV_AtObj(hex, idx)) + "'\n"; +509 } +510 if (hex.substr(idx, 2) == "17") { +511 return indent + "UTCTime " + hextoutf8(ASN1HEX.getHexOfV_AtObj(hex, idx)) + "\n"; +512 } +513 if (hex.substr(idx, 2) == "18") { +514 return indent + "GeneralizedTime " + hextoutf8(ASN1HEX.getHexOfV_AtObj(hex, idx)) + "\n"; +515 } +516 if (hex.substr(idx, 2) == "30") { +517 if (hex.substr(idx, 4) == "3000") { +518 return indent + "SEQUENCE {}\n"; +519 } +520 +521 var s = indent + "SEQUENCE\n"; +522 var aIdx = ASN1HEX.getPosArrayOfChildren_AtObj(hex, idx); +523 +524 var flagsTemp = flags; +525 +526 if ((aIdx.length == 2 || aIdx.length == 3) && +527 hex.substr(aIdx[0], 2) == "06" && +528 hex.substr(aIdx[aIdx.length - 1], 2) == "04") { // supposed X.509v3 extension +529 var oidHex = ASN1HEX.getHexOfV_AtObj(hex, aIdx[0]); +530 var oidDot = KJUR.asn1.ASN1Util.oidHexToInt(oidHex); +531 var oidName = KJUR.asn1.x509.OID.oid2name(oidDot); +532 +533 var flagsClone = JSON.parse(JSON.stringify(flags)); +534 flagsClone.x509ExtName = oidName; +535 flagsTemp = flagsClone; +536 } +537 +538 for (var i = 0; i < aIdx.length; i++) { +539 s = s + ASN1HEX.dump(hex, flagsTemp, aIdx[i], indent + " "); +540 } +541 return s; +542 } +543 if (hex.substr(idx, 2) == "31") { +544 var s = indent + "SET\n"; +545 var aIdx = ASN1HEX.getPosArrayOfChildren_AtObj(hex, idx); +546 for (var i = 0; i < aIdx.length; i++) { +547 s = s + ASN1HEX.dump(hex, flags, aIdx[i], indent + " "); +548 } +549 return s; +550 } +551 var tag = parseInt(hex.substr(idx, 2), 16); +552 if ((tag & 128) != 0) { // context specific +553 var tagNumber = tag & 31; +554 if ((tag & 32) != 0) { // structured tag +555 var s = indent + "[" + tagNumber + "]\n"; +556 var aIdx = ASN1HEX.getPosArrayOfChildren_AtObj(hex, idx); +557 for (var i = 0; i < aIdx.length; i++) { +558 s = s + ASN1HEX.dump(hex, flags, aIdx[i], indent + " "); +559 } +560 return s; +561 } else { // primitive tag +562 var v = ASN1HEX.getHexOfV_AtObj(hex, idx); +563 if (v.substr(0, 8) == "68747470") { // http +564 v = hextoutf8(v); +565 } +566 if (flags.x509ExtName === "subjectAltName" && +567 tagNumber == 2) { +568 v = hextoutf8(v); +569 } +570 +571 var s = indent + "[" + tagNumber + "] " + v + "\n"; +572 return s; +573 } +574 } +575 return indent + "UNKNOWN(" + hex.substr(idx, 2) + ") " + ASN1HEX.getHexOfV_AtObj(hex, idx) + "\n"; +576 }; +577 +578 /** +579 * check wheather the string is ASN.1 hexadecimal string or not +580 * @name isASN1HEX +581 * @memberOf ASN1HEX +582 * @function +583 * @param {String} hex string to check whether it is hexadecmal string for ASN.1 DER or not +584 * @return {Boolean} true if it is hexadecimal string of ASN.1 data otherwise false +585 * @since jsrsasign 4.8.3 asn1hex 1.1.6 +586 * @description +587 * This method checks wheather the argument 'hex' is a hexadecimal string of +588 * ASN.1 data or not. +589 * @example +590 * ASN1HEX.isASN1HEX('0203012345') → true // PROPER ASN.1 INTEGER +591 * ASN1HEX.isASN1HEX('0203012345ff') → false // TOO LONG VALUE +592 * ASN1HEX.isASN1HEX('02030123') → false // TOO SHORT VALUE +593 * ASN1HEX.isASN1HEX('fa3bcd') → false // WRONG FOR ASN.1 +594 */ +595 ASN1HEX.isASN1HEX = function(hex) { +596 if (hex.length % 2 == 1) return false; +597 +598 var intL = ASN1HEX.getIntOfL_AtObj(hex, 0); +599 var tV = hex.substr(0, 2); +600 var lV = ASN1HEX.getHexOfL_AtObj(hex, 0); +601 var hVLength = hex.length - tV.length - lV.length; +602 if (hVLength == intL * 2) return true; +603 +604 return false; +605 }; +606
    \ No newline at end of file diff --git a/api/symbols/src/jws-3.3.js.html b/api/symbols/src/jws-3.3.js.html index 6a8daaf2..75376ace 100644 --- a/api/symbols/src/jws-3.3.js.html +++ b/api/symbols/src/jws-3.3.js.html @@ -5,14 +5,14 @@ .STRN {color: #393;} .REGX {color: #339;} .line {border-right: 1px dotted #666; color: #666; font-style: normal;} -
      1 /*! jws-3.3.3 (c) 2013-2015 Kenji Urushima | kjur.github.com/jsrsasign/license
    +	
      1 /*! jws-3.3.4 (c) 2013-2016 Kenji Urushima | kjur.github.com/jsrsasign/license
       2  */
       3 /*
       4  * jws.js - JSON Web Signature(JWS) and JSON Web Token(JWT) Class
       5  *
    -  6  * version: 3.3.3 (2015 Nov 27)
    +  6  * version: 3.3.4 (2016 May 17)
       7  *
    -  8  * Copyright (c) 2010-2015 Kenji Urushima (kenji.urushima@gmail.com)
    +  8  * Copyright (c) 2010-2016 Kenji Urushima (kenji.urushima@gmail.com)
       9  *
      10  * This software is licensed under the terms of the MIT License.
      11  * http://kjur.github.com/jsrsasign/license/
    @@ -25,7 +25,7 @@
      18  * @fileOverview
      19  * @name jws-3.3.js
      20  * @author Kenji Urushima kenji.urushima@gmail.com
    - 21  * @version 3.3.3 (2015-Nov-27)
    + 21  * @version 3.3.4 (2016-May-17)
      22  * @since jsjws 1.0, jsrsasign 4.8.0
      23  * @license <a href="http://kjur.github.io/jsrsasign/license/">MIT License</a>
      24  */
    @@ -544,492 +544,510 @@
     537  * @param {Array} acceptField associative array of acceptable fields (OPTION)
     538  * @return {Boolean} true if the JWT token is valid otherwise false
     539  * @since jws 3.2.3 jsrsasign 4.8.0
    -540  * @description
    -541  * This method verifies a
    -542  * <a href="https://tools.ietf.org/html/rfc7519">RFC 7519</a> 
    -543  * JSON Web Token(JWT).
    -544  * It will verify following:
    -545  * <ul>
    -546  * <li>Header.alg
    -547  * <ul>
    -548  * <li>alg is specified in JWT header.</li>
    -549  * <li>alg is included in acceptField.alg array. (MANDATORY)</li>
    -550  * <li>alg is proper for key.</li>
    -551  * </ul>
    -552  * </li>
    -553  * <li>Payload.iss (issuer) - Payload.iss is included in acceptField.iss array if specified. (OPTION)</li>
    -554  * <li>Payload.sub (subject) - Payload.sub is included in acceptField.sub array if specified. (OPTION)</li>
    -555  * <li>Payload.aud (audience) - Payload.aud is included in acceptField.aud array or 
    -556  *     the same as value if specified. (OPTION)</li>
    -557  * <li>Time validity
    -558  * <ul>
    -559  * <li>If acceptField.verifyAt as number of UNIX origin time is specifed for validation time, 
    -560  * this method will verify at the time for it, otherwise current time will be used to verify.</li>
    -561  * <li>Payload.exp (expire) - Validation time is smaller than Payloead.exp.</li>
    -562  * <li>Payload.nbf (not before) - Validation time is greater than Payloead.nbf.</li>
    -563  * <li>Payload.iat (issued at) - Validation time is greater than Payloead.iat.</li>
    -564  * </ul>
    -565  * </li>
    -566  * <li>Payload.jti (JWT id) - Payload.jti is included in acceptField.jti if specified. (OPTION)</li>
    -567  * <li>JWS signature of JWS is valid for specified key.</li>
    -568  * </ul>
    -569  *
    -570  * @example
    -571  * // simple validation for HS256
    -572  * isValid = KJUR.jws.JWS.verifyJWT("eyJhbG...", "616161", {alg: ["HS256"]}),
    -573  *
    -574  * // full validation for RS or PS
    -575  * pubkey = KEYUTIL.getKey('-----BEGIN CERT...');
    -576  * isValid = KJUR.jws.JWS.verifyJWT('eyJh...', pubkey, {
    -577  *   alg: ['RS256', 'RS512', 'PS256', 'PS512'],
    -578  *   iss: ['http://foo.com'],
    -579  *   sub: ['mailto:john@foo.com', 'mailto:alice@foo.com'],
    -580  *   verifyAt: KJUR.jws.IntDate.get('20150520235959Z'),
    -581  *   aud: ['http://foo.com'], // aud: 'http://foo.com' is fine too.
    -582  *   jti: 'id123456'
    -583  * });
    -584  */
    -585 KJUR.jws.JWS.verifyJWT = function(sJWT, key, acceptField) {
    -586     var ns1 = KJUR.jws.JWS;
    -587 
    -588     // 1. parse JWT
    -589     var a = sJWT.split(".");
    -590     var uHeader = a[0];
    -591     var uPayload = a[1];
    -592     var uSignatureInput = uHeader + "." + uPayload;
    -593     var hSig = b64utohex(a[2]);
    -594 
    -595     // 2. parse JWS header
    -596     var pHeader = ns1.readSafeJSONString(b64utoutf8(uHeader));
    -597 
    -598     // 3. parse JWS payload
    -599     var pPayload = ns1.readSafeJSONString(b64utoutf8(uPayload));
    +540  *
    +541  * @description
    +542  * This method verifies a
    +543  * <a href="https://tools.ietf.org/html/rfc7519">RFC 7519</a> 
    +544  * JSON Web Token(JWT).
    +545  * It will verify following:
    +546  * <ul>
    +547  * <li>Header.alg
    +548  * <ul>
    +549  * <li>alg is specified in JWT header.</li>
    +550  * <li>alg is included in acceptField.alg array. (MANDATORY)</li>
    +551  * <li>alg is proper for key.</li>
    +552  * </ul>
    +553  * </li>
    +554  * <li>Payload.iss (issuer) - Payload.iss is included in acceptField.iss array if specified. (OPTION)</li>
    +555  * <li>Payload.sub (subject) - Payload.sub is included in acceptField.sub array if specified. (OPTION)</li>
    +556  * <li>Payload.aud (audience) - Payload.aud is included in acceptField.aud array or 
    +557  *     the same as value if specified. (OPTION)</li>
    +558  * <li>Time validity
    +559  * <ul>
    +560  * <li>
    +561  * If acceptField.verifyAt as number of UNIX origin time is specifed for validation time, 
    +562  * this method will verify at the time for it, otherwise current time will be used to verify.
    +563  * </li>
    +564  * <li>
    +565  * Clock of JWT generator or verifier can be fast or slow. If these clocks are
    +566  * very different, JWT validation may fail. To avoid such case, 'jsrsasign' supports
    +567  * 'acceptField.gracePeriod' parameter which specifies acceptable time difference
    +568  * of those clocks in seconds. So if you want to accept slow or fast in 2 hours,
    +569  * you can specify <code>acceptField.gracePeriod = 2 * 60 * 60;</code>.
    +570  * "gracePeriod" is zero by default.
    +571  * "gracePeriod" is supported since jsrsasign 5.0.12.
    +572  * </li>
    +573  * <li>Payload.exp (expire) - Validation time is smaller than Payload.exp + gracePeriod.</li>
    +574  * <li>Payload.nbf (not before) - Validation time is greater than Payload.nbf - gracePeriod.</li>
    +575  * <li>Payload.iat (issued at) - Validation time is greater than Payload.iat - gracePeriod.</li>
    +576  * </ul>
    +577  * </li>
    +578  * <li>Payload.jti (JWT id) - Payload.jti is included in acceptField.jti if specified. (OPTION)</li>
    +579  * <li>JWS signature of JWS is valid for specified key.</li>
    +580  * </ul>
    +581  *
    +582  * @example
    +583  * // simple validation for HS256
    +584  * isValid = KJUR.jws.JWS.verifyJWT("eyJhbG...", "616161", {alg: ["HS256"]}),
    +585  *
    +586  * // full validation for RS or PS
    +587  * pubkey = KEYUTIL.getKey('-----BEGIN CERT...');
    +588  * isValid = KJUR.jws.JWS.verifyJWT('eyJh...', pubkey, {
    +589  *   alg: ['RS256', 'RS512', 'PS256', 'PS512'],
    +590  *   iss: ['http://foo.com'],
    +591  *   sub: ['mailto:john@foo.com', 'mailto:alice@foo.com'],
    +592  *   verifyAt: KJUR.jws.IntDate.get('20150520235959Z'),
    +593  *   aud: ['http://foo.com'], // aud: 'http://foo.com' is fine too.
    +594  *   jti: 'id123456',
    +595  *   gracePeriod: 1 * 60 * 60 // accept 1 hour slow or fast
    +596  * });
    +597  */
    +598 KJUR.jws.JWS.verifyJWT = function(sJWT, key, acceptField) {
    +599     var ns1 = KJUR.jws.JWS;
     600 
    -601     // 4. algorithm ('alg' in header) check
    -602     if (pHeader.alg === undefined) return false;
    -603     if (acceptField.alg === undefined)
    -604 	throw "acceptField.alg shall be specified";
    -605     if (! ns1.inArray(pHeader.alg, acceptField.alg)) return false;
    -606 
    -607     // 5. issuer ('iss' in payload) check
    -608     if (pPayload.iss !== undefined && typeof acceptField.iss === "object") {
    -609 	if (! ns1.inArray(pPayload.iss, acceptField.iss)) return false;
    -610     }
    -611 
    -612     // 6. subject ('sub' in payload) check
    -613     if (pPayload.sub !== undefined && typeof acceptField.sub === "object") {
    -614 	if (! ns1.inArray(pPayload.sub, acceptField.sub)) return false;
    -615     }
    -616 
    -617     // 7. audience ('aud' in payload) check
    -618     if (pPayload.aud !== undefined && typeof acceptField.aud === "object") {
    -619 	if (typeof pPayload.aud == "string") {
    -620 	    if (! ns1.inArray(pPayload.aud, acceptField.aud))
    -621 		return false;
    -622 	} else if (typeof pPayload.aud == "object") {
    -623 	    if (! ns1.includedArray(pPayload.aud, acceptField.aud))
    -624 		return false;
    -625 	}
    -626     }
    -627 
    -628     // 8. time validity (nbf < now < exp) && (iat <= now)
    -629     var now = KJUR.jws.IntDate.getNow();
    -630     if (acceptField.verifyAt !== undefined && typeof acceptField.verifyAt == "number") {
    -631 	now = acceptField.verifyAt;
    -632     }
    -633 
    -634     // 8.1 expired time 'exp' check
    -635     if (pPayload.exp !== undefined && typeof pPayload.exp == "number") {
    -636 	if (pPayload.exp < now) return false;
    -637     }
    -638 
    -639     // 8.2 not before time 'nbf' check
    -640     if (pPayload.nbf !== undefined && typeof pPayload.nbf == "number") {
    -641 	if (now < pPayload.nbf) return false;
    -642     }
    -643     
    -644     // 8.3 issued at time 'iat' check
    -645     if (pPayload.iat !== undefined && typeof pPayload.iat == "number") {
    -646 	if (now < pPayload.iat) return false;
    -647     }
    -648 
    -649     // 9 JWT id 'jti' check
    -650     if (pPayload.jti !== undefined && acceptField.jti !== undefined) {
    -651       if (pPayload.jti !== acceptField.jti) return false;
    -652     }
    -653 
    -654     // 10 JWS signature check
    -655     if (! KJUR.jws.JWS.verify(sJWT, key, acceptField.alg)) return false;
    +601     // 1. parse JWT
    +602     var a = sJWT.split(".");
    +603     var uHeader = a[0];
    +604     var uPayload = a[1];
    +605     var uSignatureInput = uHeader + "." + uPayload;
    +606     var hSig = b64utohex(a[2]);
    +607 
    +608     // 2. parse JWS header
    +609     var pHeader = ns1.readSafeJSONString(b64utoutf8(uHeader));
    +610 
    +611     // 3. parse JWS payload
    +612     var pPayload = ns1.readSafeJSONString(b64utoutf8(uPayload));
    +613 
    +614     // 4. algorithm ('alg' in header) check
    +615     if (pHeader.alg === undefined) return false;
    +616     if (acceptField.alg === undefined)
    +617 	throw "acceptField.alg shall be specified";
    +618     if (! ns1.inArray(pHeader.alg, acceptField.alg)) return false;
    +619 
    +620     // 5. issuer ('iss' in payload) check
    +621     if (pPayload.iss !== undefined && typeof acceptField.iss === "object") {
    +622 	if (! ns1.inArray(pPayload.iss, acceptField.iss)) return false;
    +623     }
    +624 
    +625     // 6. subject ('sub' in payload) check
    +626     if (pPayload.sub !== undefined && typeof acceptField.sub === "object") {
    +627 	if (! ns1.inArray(pPayload.sub, acceptField.sub)) return false;
    +628     }
    +629 
    +630     // 7. audience ('aud' in payload) check
    +631     if (pPayload.aud !== undefined && typeof acceptField.aud === "object") {
    +632 	if (typeof pPayload.aud == "string") {
    +633 	    if (! ns1.inArray(pPayload.aud, acceptField.aud))
    +634 		return false;
    +635 	} else if (typeof pPayload.aud == "object") {
    +636 	    if (! ns1.includedArray(pPayload.aud, acceptField.aud))
    +637 		return false;
    +638 	}
    +639     }
    +640 
    +641     // 8. time validity 
    +642     //   (nbf - gracePeriod < now < exp + gracePeriod) && (iat - gracePeriod < now)
    +643     var now = KJUR.jws.IntDate.getNow();
    +644     if (acceptField.verifyAt !== undefined && typeof acceptField.verifyAt === "number") {
    +645 	now = acceptField.verifyAt;
    +646     }
    +647     if (acceptField.gracePeriod === undefined || 
    +648         typeof acceptField.gracePeriod !== "number") {
    +649 	acceptField.gracePeriod = 0;
    +650     }
    +651 
    +652     // 8.1 expired time 'exp' check
    +653     if (pPayload.exp !== undefined && typeof pPayload.exp == "number") {
    +654 	if (pPayload.exp + acceptField.gracePeriod < now) return false;
    +655     }
     656 
    -657     // 11 passed all check
    -658     return true;
    -659 };
    -660 
    -661 /**
    -662  * check whether array is included by another array
    -663  * @name includedArray
    -664  * @memberOf KJUR.jws.JWS
    -665  * @function
    -666  * @static
    -667  * @param {Array} a1 check whether set a1 is included by a2
    -668  * @param {Array} a2 check whether set a1 is included by a2
    -669  * @return {Boolean} check whether set a1 is included by a2
    -670  * @since jws 3.2.3
    -671  * This method verifies whether an array is included by another array.
    -672  * It doesn't care about item ordering in a array.
    -673  * @example
    -674  * KJUR.jws.JWS.includedArray(['b'], ['b', 'c', 'a']) => true
    -675  * KJUR.jws.JWS.includedArray(['a', 'b'], ['b', 'c', 'a']) => true
    -676  * KJUR.jws.JWS.includedArray(['a', 'b'], ['b', 'c']) => false
    -677  */
    -678 KJUR.jws.JWS.includedArray = function(a1, a2) {
    -679     var inArray = KJUR.jws.JWS.inArray;
    -680     if (a1 === null) return false;
    -681     if (typeof a1 !== "object") return false;
    -682     if (typeof a1.length !== "number") return false;
    -683 
    -684     for (var i = 0; i < a1.length; i++) {
    -685 	if (! inArray(a1[i], a2)) return false;
    -686     }
    -687     return true;
    -688 };
    -689 
    -690 /**
    -691  * check whether item is included by array
    -692  * @name inArray
    -693  * @memberOf KJUR.jws.JWS
    -694  * @function
    -695  * @static
    -696  * @param {String} item check whether item is included by array
    -697  * @param {Array} a check whether item is included by array
    -698  * @return {Boolean} check whether item is included by array
    -699  * @since jws 3.2.3
    -700  * This method verifies whether an item is included by an array.
    -701  * It doesn't care about item ordering in an array.
    -702  * @example
    -703  * KJUR.jws.JWS.inArray('b', ['b', 'c', 'a']) => true
    -704  * KJUR.jws.JWS.inArray('a', ['b', 'c', 'a']) => true
    -705  * KJUR.jws.JWS.inArray('a', ['b', 'c']) => false
    -706  */
    -707 KJUR.jws.JWS.inArray = function(item, a) {
    -708     if (a === null) return false;
    -709     if (typeof a !== "object") return false;
    -710     if (typeof a.length !== "number") return false;
    -711     for (var i = 0; i < a.length; i++) {
    -712 	if (a[i] == item) return true;
    -713     }
    -714     return false;
    -715 };
    -716 
    -717 /**
    -718  * static associative array of general signature algorithm name from JWS algorithm name
    -719  * @since jws 3.0.0
    -720  */
    -721 KJUR.jws.JWS.jwsalg2sigalg = {
    -722     "HS256":	"HmacSHA256",
    -723     "HS384":	"HmacSHA384",
    -724     "HS512":	"HmacSHA512",
    -725     "RS256":	"SHA256withRSA",
    -726     "RS384":	"SHA384withRSA",
    -727     "RS512":	"SHA512withRSA",
    -728     "ES256":	"SHA256withECDSA",
    -729     "ES384":	"SHA384withECDSA",
    -730     //"ES512":	"SHA512withECDSA", // unsupported because of jsrsasign's bug
    -731     "PS256":	"SHA256withRSAandMGF1",
    -732     "PS384":	"SHA384withRSAandMGF1",
    -733     "PS512":	"SHA512withRSAandMGF1",
    -734     "none":	"none",
    -735 };
    -736 
    -737 // === utility static method ==================================================
    -738 
    -739 /**
    -740  * check whether a String "s" is a safe JSON string or not.<br/>
    -741  * If a String "s" is a malformed JSON string or an other object type
    -742  * this returns 0, otherwise this returns 1.
    -743  * @name isSafeJSONString
    -744  * @memberOf KJUR.jws.JWS
    -745  * @function
    -746  * @static
    -747  * @param {String} s JSON string
    -748  * @return {Number} 1 or 0
    -749  */
    -750 KJUR.jws.JWS.isSafeJSONString = function(s, h, p) {
    -751     var o = null;
    -752     try {
    -753 	o = jsonParse(s);
    -754 	if (typeof o != "object") return 0;
    -755 	if (o.constructor === Array) return 0;
    -756 	if (h) h[p] = o;
    -757 	return 1;
    -758     } catch (ex) {
    -759 	return 0;
    -760     }
    -761 };
    -762 
    -763 /**
    -764  * read a String "s" as JSON object if it is safe.<br/>
    -765  * If a String "s" is a malformed JSON string or not JSON string,
    -766  * this returns null, otherwise returns JSON object.
    -767  * @name readSafeJSONString
    -768  * @memberOf KJUR.jws.JWS
    -769  * @function
    -770  * @static
    -771  * @param {String} s JSON string
    -772  * @return {Object} JSON object or null
    -773  * @since 1.1.1
    -774  */
    -775 KJUR.jws.JWS.readSafeJSONString = function(s) {
    -776     var o = null;
    -777     try {
    -778 	o = jsonParse(s);
    -779 	if (typeof o != "object") return null;
    -780 	if (o.constructor === Array) return null;
    -781 	return o;
    -782     } catch (ex) {
    -783 	return null;
    -784     }
    -785 };
    -786 
    -787 /**
    -788  * get Encoed Signature Value from JWS string.<br/>
    -789  * @name getEncodedSignatureValueFromJWS
    -790  * @memberOf KJUR.jws.JWS
    -791  * @function
    -792  * @static
    -793  * @param {String} sJWS JWS signature string to be verified
    -794  * @return {String} string of Encoded Signature Value 
    -795  * @throws if sJWS is not comma separated string such like "Header.Payload.Signature".
    -796  */
    -797 KJUR.jws.JWS.getEncodedSignatureValueFromJWS = function(sJWS) {
    -798     if (sJWS.match(/^[^.]+\.[^.]+\.([^.]+)$/) == null) {
    -799 	throw "JWS signature is not a form of 'Head.Payload.SigValue'.";
    -800     }
    -801     return RegExp.$1;
    -802 };
    -803 
    -804 /**
    -805  * get RFC 7638 JWK thumbprint from JWK object
    -806  * @name getJWKthumbprint
    -807  * @memberOf KJUR.jws.JWS
    -808  * @function
    -809  * @static
    -810  * @param {String} o JWK object to be calculated thumbprint
    -811  * @return {String} Base64 URL encoded JWK thumbprint value
    -812  * @since jsrsasign 5.0.2 jws 3.3.2
    -813  * @description
    -814  * This method calculates JWK thmubprint for specified JWK object
    -815  * as described in 
    -816  * <a href="https://tools.ietf.org/html/rfc7638">RFC 7638</a>.
    -817  * It supports all type of "kty". (i.e. "RSA", "EC" and "oct"
    -818  * (for symmetric key))
    -819  * Working sample is 
    -820  * <a href="https://kjur.github.io/jsrsasign/sample/tool_jwktp.html">here</a>.
    -821  * @example
    -822  * jwk = {"kty":"RSA", "n":"0vx...", "e":"AQAB", ...};
    -823  * thumbprint = KJUR.jws.JWS.getJWKthumbprint(jwk);
    -824  */
    -825 KJUR.jws.JWS.getJWKthumbprint = function(o) {
    -826     if (o.kty !== "RSA" &&
    -827 	o.kty !== "EC" &&
    -828 	o.kty !== "oct")
    -829 	throw "unsupported algorithm for JWK Thumprint";
    -830 
    -831     // 1. get canonically ordered json string
    -832     var s = '{';
    -833     if (o.kty === "RSA") {
    -834 	if (typeof o.n != "string" || typeof o.e != "string")
    -835 	    throw "wrong n and e value for RSA key";
    -836 	s += '"' + 'e' + '":"' + o.e + '",';
    -837 	s += '"' + 'kty' + '":"' + o.kty + '",';
    -838 	s += '"' + 'n' + '":"' + o.n + '"}';
    -839     } else if (o.kty === "EC") {
    -840 	if (typeof o.crv != "string" || 
    -841 	    typeof o.x != "string" ||
    -842 	    typeof o.y != "string")
    -843 	    throw "wrong crv, x and y value for EC key";
    -844 	s += '"' + 'crv' + '":"' + o.crv + '",';
    -845 	s += '"' + 'kty' + '":"' + o.kty + '",';
    -846 	s += '"' + 'x' + '":"' + o.x + '",';
    -847 	s += '"' + 'y' + '":"' + o.y + '"}';
    -848     } else if (o.kty === "oct") {
    -849 	if (typeof o.k != "string")
    -850 	    throw "wrong k value for oct(symmetric) key";
    -851 	s += '"' + 'kty' + '":"' + o.kty + '",';
    -852 	s += '"' + 'k' + '":"' + o.k + '"}';
    -853     }
    -854     //alert(s);
    -855 
    -856     // 2. get thumb print
    -857     var hJWK = rstrtohex(s);
    -858     var hash = KJUR.crypto.Util.hashHex(hJWK, "sha256");
    -859     var hashB64U = hextob64u(hash);
    -860 
    -861     return hashB64U;
    -862 };
    -863 
    -864 /**
    -865  * IntDate class for time representation for JSON Web Token(JWT)
    -866  * @class KJUR.jws.IntDate class
    -867  * @name KJUR.jws.IntDate
    -868  * @since jws 3.0.1
    -869  * @description
    -870  * Utility class for IntDate which is integer representation of UNIX origin time
    -871  * used in JSON Web Token(JWT).
    -872  */
    -873 KJUR.jws.IntDate = {};
    -874 
    -875 /**
    -876  * get UNIX origin time from by string
    -877  * @name get
    -878  * @memberOf KJUR.jws.IntDate
    -879  * @function
    -880  * @static
    -881  * @param {String} s string of time representation
    -882  * @return {Integer} UNIX origin time in seconds for argument 's'
    -883  * @since jws 3.0.1
    -884  * @throws "unsupported format: s" when malformed format
    -885  * @description
    -886  * This method will accept following representation of time.
    -887  * <ul>
    -888  * <li>now - current time</li>
    -889  * <li>now + 1hour - after 1 hour from now</li>
    -890  * <li>now + 1day - after 1 day from now</li>
    -891  * <li>now + 1month - after 30 days from now</li>
    -892  * <li>now + 1year - after 365 days from now</li>
    -893  * <li>YYYYmmDDHHMMSSZ - UTC time (ex. 20130828235959Z)</li>
    -894  * <li>number - UNIX origin time (seconds from 1970-01-01 00:00:00) (ex. 1377714748)</li>
    -895  * </ul>
    -896  */
    -897 KJUR.jws.IntDate.get = function(s) {
    -898     if (s == "now") {
    -899 	return KJUR.jws.IntDate.getNow();
    -900     } else if (s == "now + 1hour") {
    -901 	return KJUR.jws.IntDate.getNow() + 60 * 60;
    -902     } else if (s == "now + 1day") {
    -903 	return KJUR.jws.IntDate.getNow() + 60 * 60 * 24;
    -904     } else if (s == "now + 1month") {
    -905 	return KJUR.jws.IntDate.getNow() + 60 * 60 * 24 * 30;
    -906     } else if (s == "now + 1year") {
    -907 	return KJUR.jws.IntDate.getNow() + 60 * 60 * 24 * 365;
    -908     } else if (s.match(/Z$/)) {
    -909 	return KJUR.jws.IntDate.getZulu(s);
    -910     } else if (s.match(/^[0-9]+$/)) {
    -911 	return parseInt(s);
    -912     }
    -913     throw "unsupported format: " + s;
    -914 };
    -915 
    -916 /**
    -917  * get UNIX origin time from Zulu time representation string
    -918  * @name getZulu
    -919  * @memberOf KJUR.jws.IntDate
    -920  * @function
    -921  * @static
    -922  * @param {String} s string of Zulu time representation (ex. 20151012125959Z)
    -923  * @return {Integer} UNIX origin time in seconds for argument 's'
    -924  * @since jws 3.0.1
    -925  * @throws "unsupported format: s" when malformed format
    -926  * @description
    -927  * This method provides UNIX origin time from Zulu time.
    -928  * Following representations are supported:
    -929  * <ul>
    -930  * <li>YYYYMMDDHHmmSSZ - GeneralizedTime format</li>
    -931  * <li>YYMMDDHHmmSSZ - UTCTime format. If YY is greater or equal to 
    -932  * 50 then it represents 19YY otherwise 20YY.</li>
    -933  * </ul>
    -934  * @example
    -935  * KJUR.jws.IntDate.getZulu("20151012125959Z") => 1478...
    -936  * KJUR.jws.IntDate.getZulu("151012125959Z") => 1478...
    -937  */
    -938 KJUR.jws.IntDate.getZulu = function(s) {
    -939     var a;
    -940     if (a = s.match(/(\d+)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)Z/)) {
    -941         var sYear = RegExp.$1;
    -942 	var year = parseInt(sYear);
    -943 	if (sYear.length == 4) {
    -944         } else if (sYear.length == 2) {
    -945 	    if (50 <= year && year < 100) {
    -946 		year = 1900 + year;
    -947 	    } else if (0 <= year && year < 50) {
    -948 		year = 2000 + year;
    -949 	    } else {
    -950 		throw "malformed year string for UTCTime";
    -951 	    }
    -952 	} else {
    -953 	    throw "malformed year string";
    -954 	}
    -955 	var month = parseInt(RegExp.$2) - 1;
    -956 	var day = parseInt(RegExp.$3);
    -957 	var hour = parseInt(RegExp.$4);
    -958 	var min = parseInt(RegExp.$5);
    -959 	var sec = parseInt(RegExp.$6);
    -960 	var d = new Date(Date.UTC(year, month, day, hour, min, sec));
    -961 	return ~~(d / 1000);
    -962     }
    -963     throw "unsupported format: " + s;
    -964 };
    -965 
    -966 /**
    -967  * get UNIX origin time of current time
    -968  * @name getNow
    -969  * @memberOf KJUR.jws.IntDate
    -970  * @function
    -971  * @static
    -972  * @return {Integer} UNIX origin time for current time
    -973  * @since jws 3.0.1
    -974  * @description
    -975  * This method provides UNIX origin time for current time
    -976  * @example
    -977  * KJUR.jws.IntDate.getNow() => 1478...
    -978  */
    -979 KJUR.jws.IntDate.getNow = function() {
    -980     var d = ~~(new Date() / 1000);
    -981     return d;
    +657     // 8.2 not before time 'nbf' check
    +658     if (pPayload.nbf !== undefined && typeof pPayload.nbf == "number") {
    +659 	if (now < pPayload.nbf - acceptField.gracePeriod) return false;
    +660     }
    +661     
    +662     // 8.3 issued at time 'iat' check
    +663     if (pPayload.iat !== undefined && typeof pPayload.iat == "number") {
    +664 	if (now < pPayload.iat - acceptField.gracePeriod) return false;
    +665     }
    +666 
    +667     // 9 JWT id 'jti' check
    +668     if (pPayload.jti !== undefined && acceptField.jti !== undefined) {
    +669       if (pPayload.jti !== acceptField.jti) return false;
    +670     }
    +671 
    +672     // 10 JWS signature check
    +673     if (! KJUR.jws.JWS.verify(sJWT, key, acceptField.alg)) return false;
    +674 
    +675     // 11 passed all check
    +676     return true;
    +677 };
    +678 
    +679 /**
    +680  * check whether array is included by another array
    +681  * @name includedArray
    +682  * @memberOf KJUR.jws.JWS
    +683  * @function
    +684  * @static
    +685  * @param {Array} a1 check whether set a1 is included by a2
    +686  * @param {Array} a2 check whether set a1 is included by a2
    +687  * @return {Boolean} check whether set a1 is included by a2
    +688  * @since jws 3.2.3
    +689  * This method verifies whether an array is included by another array.
    +690  * It doesn't care about item ordering in a array.
    +691  * @example
    +692  * KJUR.jws.JWS.includedArray(['b'], ['b', 'c', 'a']) => true
    +693  * KJUR.jws.JWS.includedArray(['a', 'b'], ['b', 'c', 'a']) => true
    +694  * KJUR.jws.JWS.includedArray(['a', 'b'], ['b', 'c']) => false
    +695  */
    +696 KJUR.jws.JWS.includedArray = function(a1, a2) {
    +697     var inArray = KJUR.jws.JWS.inArray;
    +698     if (a1 === null) return false;
    +699     if (typeof a1 !== "object") return false;
    +700     if (typeof a1.length !== "number") return false;
    +701 
    +702     for (var i = 0; i < a1.length; i++) {
    +703 	if (! inArray(a1[i], a2)) return false;
    +704     }
    +705     return true;
    +706 };
    +707 
    +708 /**
    +709  * check whether item is included by array
    +710  * @name inArray
    +711  * @memberOf KJUR.jws.JWS
    +712  * @function
    +713  * @static
    +714  * @param {String} item check whether item is included by array
    +715  * @param {Array} a check whether item is included by array
    +716  * @return {Boolean} check whether item is included by array
    +717  * @since jws 3.2.3
    +718  * This method verifies whether an item is included by an array.
    +719  * It doesn't care about item ordering in an array.
    +720  * @example
    +721  * KJUR.jws.JWS.inArray('b', ['b', 'c', 'a']) => true
    +722  * KJUR.jws.JWS.inArray('a', ['b', 'c', 'a']) => true
    +723  * KJUR.jws.JWS.inArray('a', ['b', 'c']) => false
    +724  */
    +725 KJUR.jws.JWS.inArray = function(item, a) {
    +726     if (a === null) return false;
    +727     if (typeof a !== "object") return false;
    +728     if (typeof a.length !== "number") return false;
    +729     for (var i = 0; i < a.length; i++) {
    +730 	if (a[i] == item) return true;
    +731     }
    +732     return false;
    +733 };
    +734 
    +735 /**
    +736  * static associative array of general signature algorithm name from JWS algorithm name
    +737  * @since jws 3.0.0
    +738  */
    +739 KJUR.jws.JWS.jwsalg2sigalg = {
    +740     "HS256":	"HmacSHA256",
    +741     "HS384":	"HmacSHA384",
    +742     "HS512":	"HmacSHA512",
    +743     "RS256":	"SHA256withRSA",
    +744     "RS384":	"SHA384withRSA",
    +745     "RS512":	"SHA512withRSA",
    +746     "ES256":	"SHA256withECDSA",
    +747     "ES384":	"SHA384withECDSA",
    +748     //"ES512":	"SHA512withECDSA", // unsupported because of jsrsasign's bug
    +749     "PS256":	"SHA256withRSAandMGF1",
    +750     "PS384":	"SHA384withRSAandMGF1",
    +751     "PS512":	"SHA512withRSAandMGF1",
    +752     "none":	"none",
    +753 };
    +754 
    +755 // === utility static method ==================================================
    +756 
    +757 /**
    +758  * check whether a String "s" is a safe JSON string or not.<br/>
    +759  * If a String "s" is a malformed JSON string or an other object type
    +760  * this returns 0, otherwise this returns 1.
    +761  * @name isSafeJSONString
    +762  * @memberOf KJUR.jws.JWS
    +763  * @function
    +764  * @static
    +765  * @param {String} s JSON string
    +766  * @return {Number} 1 or 0
    +767  */
    +768 KJUR.jws.JWS.isSafeJSONString = function(s, h, p) {
    +769     var o = null;
    +770     try {
    +771 	o = jsonParse(s);
    +772 	if (typeof o != "object") return 0;
    +773 	if (o.constructor === Array) return 0;
    +774 	if (h) h[p] = o;
    +775 	return 1;
    +776     } catch (ex) {
    +777 	return 0;
    +778     }
    +779 };
    +780 
    +781 /**
    +782  * read a String "s" as JSON object if it is safe.<br/>
    +783  * If a String "s" is a malformed JSON string or not JSON string,
    +784  * this returns null, otherwise returns JSON object.
    +785  * @name readSafeJSONString
    +786  * @memberOf KJUR.jws.JWS
    +787  * @function
    +788  * @static
    +789  * @param {String} s JSON string
    +790  * @return {Object} JSON object or null
    +791  * @since 1.1.1
    +792  */
    +793 KJUR.jws.JWS.readSafeJSONString = function(s) {
    +794     var o = null;
    +795     try {
    +796 	o = jsonParse(s);
    +797 	if (typeof o != "object") return null;
    +798 	if (o.constructor === Array) return null;
    +799 	return o;
    +800     } catch (ex) {
    +801 	return null;
    +802     }
    +803 };
    +804 
    +805 /**
    +806  * get Encoed Signature Value from JWS string.<br/>
    +807  * @name getEncodedSignatureValueFromJWS
    +808  * @memberOf KJUR.jws.JWS
    +809  * @function
    +810  * @static
    +811  * @param {String} sJWS JWS signature string to be verified
    +812  * @return {String} string of Encoded Signature Value 
    +813  * @throws if sJWS is not comma separated string such like "Header.Payload.Signature".
    +814  */
    +815 KJUR.jws.JWS.getEncodedSignatureValueFromJWS = function(sJWS) {
    +816     if (sJWS.match(/^[^.]+\.[^.]+\.([^.]+)$/) == null) {
    +817 	throw "JWS signature is not a form of 'Head.Payload.SigValue'.";
    +818     }
    +819     return RegExp.$1;
    +820 };
    +821 
    +822 /**
    +823  * get RFC 7638 JWK thumbprint from JWK object
    +824  * @name getJWKthumbprint
    +825  * @memberOf KJUR.jws.JWS
    +826  * @function
    +827  * @static
    +828  * @param {String} o JWK object to be calculated thumbprint
    +829  * @return {String} Base64 URL encoded JWK thumbprint value
    +830  * @since jsrsasign 5.0.2 jws 3.3.2
    +831  * @description
    +832  * This method calculates JWK thmubprint for specified JWK object
    +833  * as described in 
    +834  * <a href="https://tools.ietf.org/html/rfc7638">RFC 7638</a>.
    +835  * It supports all type of "kty". (i.e. "RSA", "EC" and "oct"
    +836  * (for symmetric key))
    +837  * Working sample is 
    +838  * <a href="https://kjur.github.io/jsrsasign/sample/tool_jwktp.html">here</a>.
    +839  * @example
    +840  * jwk = {"kty":"RSA", "n":"0vx...", "e":"AQAB", ...};
    +841  * thumbprint = KJUR.jws.JWS.getJWKthumbprint(jwk);
    +842  */
    +843 KJUR.jws.JWS.getJWKthumbprint = function(o) {
    +844     if (o.kty !== "RSA" &&
    +845 	o.kty !== "EC" &&
    +846 	o.kty !== "oct")
    +847 	throw "unsupported algorithm for JWK Thumprint";
    +848 
    +849     // 1. get canonically ordered json string
    +850     var s = '{';
    +851     if (o.kty === "RSA") {
    +852 	if (typeof o.n != "string" || typeof o.e != "string")
    +853 	    throw "wrong n and e value for RSA key";
    +854 	s += '"' + 'e' + '":"' + o.e + '",';
    +855 	s += '"' + 'kty' + '":"' + o.kty + '",';
    +856 	s += '"' + 'n' + '":"' + o.n + '"}';
    +857     } else if (o.kty === "EC") {
    +858 	if (typeof o.crv != "string" || 
    +859 	    typeof o.x != "string" ||
    +860 	    typeof o.y != "string")
    +861 	    throw "wrong crv, x and y value for EC key";
    +862 	s += '"' + 'crv' + '":"' + o.crv + '",';
    +863 	s += '"' + 'kty' + '":"' + o.kty + '",';
    +864 	s += '"' + 'x' + '":"' + o.x + '",';
    +865 	s += '"' + 'y' + '":"' + o.y + '"}';
    +866     } else if (o.kty === "oct") {
    +867 	if (typeof o.k != "string")
    +868 	    throw "wrong k value for oct(symmetric) key";
    +869 	s += '"' + 'kty' + '":"' + o.kty + '",';
    +870 	s += '"' + 'k' + '":"' + o.k + '"}';
    +871     }
    +872     //alert(s);
    +873 
    +874     // 2. get thumb print
    +875     var hJWK = rstrtohex(s);
    +876     var hash = KJUR.crypto.Util.hashHex(hJWK, "sha256");
    +877     var hashB64U = hextob64u(hash);
    +878 
    +879     return hashB64U;
    +880 };
    +881 
    +882 /**
    +883  * IntDate class for time representation for JSON Web Token(JWT)
    +884  * @class KJUR.jws.IntDate class
    +885  * @name KJUR.jws.IntDate
    +886  * @since jws 3.0.1
    +887  * @description
    +888  * Utility class for IntDate which is integer representation of UNIX origin time
    +889  * used in JSON Web Token(JWT).
    +890  */
    +891 KJUR.jws.IntDate = {};
    +892 
    +893 /**
    +894  * get UNIX origin time from by string
    +895  * @name get
    +896  * @memberOf KJUR.jws.IntDate
    +897  * @function
    +898  * @static
    +899  * @param {String} s string of time representation
    +900  * @return {Integer} UNIX origin time in seconds for argument 's'
    +901  * @since jws 3.0.1
    +902  * @throws "unsupported format: s" when malformed format
    +903  * @description
    +904  * This method will accept following representation of time.
    +905  * <ul>
    +906  * <li>now - current time</li>
    +907  * <li>now + 1hour - after 1 hour from now</li>
    +908  * <li>now + 1day - after 1 day from now</li>
    +909  * <li>now + 1month - after 30 days from now</li>
    +910  * <li>now + 1year - after 365 days from now</li>
    +911  * <li>YYYYmmDDHHMMSSZ - UTC time (ex. 20130828235959Z)</li>
    +912  * <li>number - UNIX origin time (seconds from 1970-01-01 00:00:00) (ex. 1377714748)</li>
    +913  * </ul>
    +914  */
    +915 KJUR.jws.IntDate.get = function(s) {
    +916     if (s == "now") {
    +917 	return KJUR.jws.IntDate.getNow();
    +918     } else if (s == "now + 1hour") {
    +919 	return KJUR.jws.IntDate.getNow() + 60 * 60;
    +920     } else if (s == "now + 1day") {
    +921 	return KJUR.jws.IntDate.getNow() + 60 * 60 * 24;
    +922     } else if (s == "now + 1month") {
    +923 	return KJUR.jws.IntDate.getNow() + 60 * 60 * 24 * 30;
    +924     } else if (s == "now + 1year") {
    +925 	return KJUR.jws.IntDate.getNow() + 60 * 60 * 24 * 365;
    +926     } else if (s.match(/Z$/)) {
    +927 	return KJUR.jws.IntDate.getZulu(s);
    +928     } else if (s.match(/^[0-9]+$/)) {
    +929 	return parseInt(s);
    +930     }
    +931     throw "unsupported format: " + s;
    +932 };
    +933 
    +934 /**
    +935  * get UNIX origin time from Zulu time representation string
    +936  * @name getZulu
    +937  * @memberOf KJUR.jws.IntDate
    +938  * @function
    +939  * @static
    +940  * @param {String} s string of Zulu time representation (ex. 20151012125959Z)
    +941  * @return {Integer} UNIX origin time in seconds for argument 's'
    +942  * @since jws 3.0.1
    +943  * @throws "unsupported format: s" when malformed format
    +944  * @description
    +945  * This method provides UNIX origin time from Zulu time.
    +946  * Following representations are supported:
    +947  * <ul>
    +948  * <li>YYYYMMDDHHmmSSZ - GeneralizedTime format</li>
    +949  * <li>YYMMDDHHmmSSZ - UTCTime format. If YY is greater or equal to 
    +950  * 50 then it represents 19YY otherwise 20YY.</li>
    +951  * </ul>
    +952  * @example
    +953  * KJUR.jws.IntDate.getZulu("20151012125959Z") => 1478...
    +954  * KJUR.jws.IntDate.getZulu("151012125959Z") => 1478...
    +955  */
    +956 KJUR.jws.IntDate.getZulu = function(s) {
    +957     var a;
    +958     if (a = s.match(/(\d+)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)Z/)) {
    +959         var sYear = RegExp.$1;
    +960 	var year = parseInt(sYear);
    +961 	if (sYear.length == 4) {
    +962         } else if (sYear.length == 2) {
    +963 	    if (50 <= year && year < 100) {
    +964 		year = 1900 + year;
    +965 	    } else if (0 <= year && year < 50) {
    +966 		year = 2000 + year;
    +967 	    } else {
    +968 		throw "malformed year string for UTCTime";
    +969 	    }
    +970 	} else {
    +971 	    throw "malformed year string";
    +972 	}
    +973 	var month = parseInt(RegExp.$2) - 1;
    +974 	var day = parseInt(RegExp.$3);
    +975 	var hour = parseInt(RegExp.$4);
    +976 	var min = parseInt(RegExp.$5);
    +977 	var sec = parseInt(RegExp.$6);
    +978 	var d = new Date(Date.UTC(year, month, day, hour, min, sec));
    +979 	return ~~(d / 1000);
    +980     }
    +981     throw "unsupported format: " + s;
     982 };
     983 
     984 /**
    -985  * get UTC time string from UNIX origin time value
    -986  * @name intDate2UTCString
    +985  * get UNIX origin time of current time
    +986  * @name getNow
     987  * @memberOf KJUR.jws.IntDate
     988  * @function
     989  * @static
    -990  * @param {Integer} intDate UNIX origin time value (ex. 1478...)
    -991  * @return {String} UTC time string
    -992  * @since jws 3.0.1
    -993  * @description
    -994  * This method provides UTC time string for UNIX origin time value.
    -995  * @example
    -996  * KJUR.jws.IntDate.intDate2UTCString(1478...) => "2015 Oct ..."
    -997  */
    -998 KJUR.jws.IntDate.intDate2UTCString = function(intDate) {
    -999     var d = new Date(intDate * 1000);
    -1000     return d.toUTCString();
    -1001 };
    -1002 
    -1003 /**
    -1004  * get UTC time string from UNIX origin time value
    -1005  * @name intDate2Zulu
    -1006  * @memberOf KJUR.jws.IntDate
    -1007  * @function
    -1008  * @static
    -1009  * @param {Integer} intDate UNIX origin time value (ex. 1478...)
    -1010  * @return {String} Zulu time string
    -1011  * @since jws 3.0.1
    -1012  * @description
    -1013  * This method provides Zulu time string for UNIX origin time value.
    -1014  * @example
    -1015  * KJUR.jws.IntDate.intDate2UTCString(1478...) => "20151012...Z"
    -1016  */
    -1017 KJUR.jws.IntDate.intDate2Zulu = function(intDate) {
    -1018     var d = new Date(intDate * 1000);
    -1019     var year = ("0000" + d.getUTCFullYear()).slice(-4);    
    -1020     var mon =  ("00" + (d.getUTCMonth() + 1)).slice(-2);    
    -1021     var day =  ("00" + d.getUTCDate()).slice(-2);    
    -1022     var hour = ("00" + d.getUTCHours()).slice(-2);    
    -1023     var min =  ("00" + d.getUTCMinutes()).slice(-2);    
    -1024     var sec =  ("00" + d.getUTCSeconds()).slice(-2);    
    -1025     return year + mon + day + hour + min + sec + "Z";
    -1026 };
    -1027 
    -1028 
    \ No newline at end of file +990 * @return {Integer} UNIX origin time for current time +991 * @since jws 3.0.1 +992 * @description +993 * This method provides UNIX origin time for current time +994 * @example +995 * KJUR.jws.IntDate.getNow() => 1478... +996 */
    +997 KJUR.jws.IntDate.getNow = function() { +998 var d = ~~(new Date() / 1000); +999 return d; +1000 }; +1001 +1002 /** +1003 * get UTC time string from UNIX origin time value +1004 * @name intDate2UTCString +1005 * @memberOf KJUR.jws.IntDate +1006 * @function +1007 * @static +1008 * @param {Integer} intDate UNIX origin time value (ex. 1478...) +1009 * @return {String} UTC time string +1010 * @since jws 3.0.1 +1011 * @description +1012 * This method provides UTC time string for UNIX origin time value. +1013 * @example +1014 * KJUR.jws.IntDate.intDate2UTCString(1478...) => "2015 Oct ..." +1015 */ +1016 KJUR.jws.IntDate.intDate2UTCString = function(intDate) { +1017 var d = new Date(intDate * 1000); +1018 return d.toUTCString(); +1019 }; +1020 +1021 /** +1022 * get UTC time string from UNIX origin time value +1023 * @name intDate2Zulu +1024 * @memberOf KJUR.jws.IntDate +1025 * @function +1026 * @static +1027 * @param {Integer} intDate UNIX origin time value (ex. 1478...) +1028 * @return {String} Zulu time string +1029 * @since jws 3.0.1 +1030 * @description +1031 * This method provides Zulu time string for UNIX origin time value. +1032 * @example +1033 * KJUR.jws.IntDate.intDate2UTCString(1478...) => "20151012...Z" +1034 */ +1035 KJUR.jws.IntDate.intDate2Zulu = function(intDate) { +1036 var d = new Date(intDate * 1000); +1037 var year = ("0000" + d.getUTCFullYear()).slice(-4); +1038 var mon = ("00" + (d.getUTCMonth() + 1)).slice(-2); +1039 var day = ("00" + d.getUTCDate()).slice(-2); +1040 var hour = ("00" + d.getUTCHours()).slice(-2); +1041 var min = ("00" + d.getUTCMinutes()).slice(-2); +1042 var sec = ("00" + d.getUTCSeconds()).slice(-2); +1043 return year + mon + day + hour + min + sec + "Z"; +1044 }; +1045 +1046
    \ No newline at end of file diff --git a/asn1hex-1.1.js b/asn1hex-1.1.js index ff4694e5..6b665d24 100644 --- a/asn1hex-1.1.js +++ b/asn1hex-1.1.js @@ -1,9 +1,9 @@ -/*! asn1hex-1.1.6.js (c) 2012-2015 Kenji Urushima | kjur.github.com/jsrsasign/license +/*! asn1hex-1.1.6.js (c) 2012-2016 Kenji Urushima | kjur.github.com/jsrsasign/license */ /* * asn1hex.js - Hexadecimal represented ASN.1 string library * - * Copyright (c) 2010-2015 Kenji Urushima (kenji.urushima@gmail.com) + * Copyright (c) 2010-2016 Kenji Urushima (kenji.urushima@gmail.com) * * This software is licensed under the terms of the MIT License. * http://kjur.github.com/jsrsasign/license/ @@ -38,6 +38,42 @@ * @name ASN1HEX * @class ASN.1 DER encoded hexadecimal string utility class * @since jsrsasign 1.1 + * @description + * This class provides a parser for hexadecimal string of + * DER encoded ASN.1 binary data. + * Here are major methods of this class. + * */ var ASN1HEX = new function() { /** @@ -371,16 +407,19 @@ ASN1HEX.hextooidstr = function(hex) { * ASN1HEX.dump('0203012345') * ↓ * INTEGER 012345 + * * // ASN.1 Object Identifier * ASN1HEX.dump('06052b0e03021a') * ↓ * ObjectIdentifier sha1 (1 3 14 3 2 26) + * * // ASN.1 SEQUENCE * ASN1HEX.dump('3006020101020102') * ↓ * SEQUENCE * INTEGER 01 * INTEGER 02 + * * // ASN.1 DUMP FOR X.509 CERTIFICATE * ASN1HEX.dump(X509.pemToHex(certPEM)) * ↓ diff --git a/bower.json b/bower.json index 579ef600..04f8be3d 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "kjur-jsrsasign", - "version": "5.0.11", + "version": "5.0.12", "main": "jsrsasign-latest-all-min.js", "description": "The 'jsrsasign' (RSA-Sign JavaScript Library) is an opensource free cryptography library supporting RSA/RSAPSS/ECDSA/DSA signing/validation, ASN.1, PKCS#1/5/8 private/public key, X.509 certificate, CRL CMS SignedData, TimeStamp, CAdES, JWS and JWT in pure JavaScript.", "license": "MIT", diff --git a/jsrsasign-latest-all-min.js b/jsrsasign-latest-all-min.js index 200784de..258c7027 100644 --- a/jsrsasign-latest-all-min.js +++ b/jsrsasign-latest-all-min.js @@ -1,5 +1,5 @@ /* - * jsrsasign 5.0.11 (c) 2010-2016 Kenji Urushima | kjur.github.com/jsrsasign/license + * jsrsasign 5.0.12 (c) 2010-2016 Kenji Urushima | kjur.github.com/jsrsasign/license */ /* @@ -278,9 +278,9 @@ var _RE_HEXDECONLY=new RegExp("");_RE_HEXDECONLY.compile("[^0-9a-f]","gi");funct /*! x509-1.1.9.js (c) 2012-2016 Kenji Urushima | kjur.github.com/jsrsasign/license */ function X509(){this.subjectPublicKeyRSA=null;this.subjectPublicKeyRSA_hN=null;this.subjectPublicKeyRSA_hE=null;this.hex=null;this.getSerialNumberHex=function(){return ASN1HEX.getDecendantHexVByNthList(this.hex,0,[0,1])};this.getSignatureAlgorithmField=function(){var b=ASN1HEX.getDecendantHexVByNthList(this.hex,0,[0,2,0]);var a=KJUR.asn1.ASN1Util.oidHexToInt(b);var c=KJUR.asn1.x509.OID.oid2name(a);return c};this.getIssuerHex=function(){return ASN1HEX.getDecendantHexTLVByNthList(this.hex,0,[0,3])};this.getIssuerString=function(){return X509.hex2dn(ASN1HEX.getDecendantHexTLVByNthList(this.hex,0,[0,3]))};this.getSubjectHex=function(){return ASN1HEX.getDecendantHexTLVByNthList(this.hex,0,[0,5])};this.getSubjectString=function(){return X509.hex2dn(ASN1HEX.getDecendantHexTLVByNthList(this.hex,0,[0,5]))};this.getNotBefore=function(){var a=ASN1HEX.getDecendantHexVByNthList(this.hex,0,[0,4,0]);a=a.replace(/(..)/g,"%$1");a=decodeURIComponent(a);return a};this.getNotAfter=function(){var a=ASN1HEX.getDecendantHexVByNthList(this.hex,0,[0,4,1]);a=a.replace(/(..)/g,"%$1");a=decodeURIComponent(a);return a};this.readCertPEM=function(c){var e=X509.pemToHex(c);var b=X509.getPublicKeyHexArrayFromCertHex(e);var d=new RSAKey();d.setPublic(b[0],b[1]);this.subjectPublicKeyRSA=d;this.subjectPublicKeyRSA_hN=b[0];this.subjectPublicKeyRSA_hE=b[1];this.hex=e};this.readCertPEMWithoutRSAInit=function(c){var d=X509.pemToHex(c);var b=X509.getPublicKeyHexArrayFromCertHex(d);this.subjectPublicKeyRSA.setPublic(b[0],b[1]);this.subjectPublicKeyRSA_hN=b[0];this.subjectPublicKeyRSA_hE=b[1];this.hex=d};this.getInfo=function(){var p="Basic Fields\n";p+=" serial number: "+this.getSerialNumberHex()+"\n";p+=" signature algorithm: "+this.getSignatureAlgorithmField()+"\n";p+=" issuer: "+this.getIssuerString()+"\n";p+=" notBefore: "+this.getNotBefore()+"\n";p+=" notAfter: "+this.getNotAfter()+"\n";p+=" subject: "+this.getSubjectString()+"\n";p+=" subject public key info: \n";var j=X509.getSubjectPublicKeyInfoPosFromCertHex(this.hex);var d=ASN1HEX.getHexOfTLV_AtObj(this.hex,j);var n=KEYUTIL.getKey(d,null,"pkcs8pub");if(n instanceof RSAKey){p+=" key algorithm: RSA\n";p+=" n="+n.n.toString(16).substr(0,16)+"...\n";p+=" e="+n.e.toString(16)+"\n"}p+="X509v3 Extensions:\n";var m=X509.getV3ExtInfoListOfCertHex(this.hex);for(var e=0;e0){var c=":"+j.join(":")+":";if(c.indexOf(":"+h+":")==-1){throw"algorithm '"+h+"' not accepted in the list"}}if(h!="none"&&t===null){throw"key shall be specified to verify."}if(typeof t=="string"&&t.indexOf("-----BEGIN ")!=-1){t=KEYUTIL.getKey(t)}if(s=="RS"||s=="PS"){if(!(t instanceof RSAKey)){throw"key shall be a RSAKey obj for RS* and PS* algs"}}if(s=="ES"){if(!(t instanceof KJUR.crypto.ECDSA)){throw"key shall be a ECDSA obj for ES* algs"}}if(h=="none"){}var n=null;if(m.jwsalg2sigalg[i.alg]===undefined){throw"unsupported alg name: "+h}else{n=m.jwsalg2sigalg[h]}if(n=="none"){throw"not supported"}else{if(n.substr(0,4)=="Hmac"){var k=null;if(t===undefined){throw"hexadecimal key shall be specified for HMAC"}var g=new KJUR.crypto.Mac({alg:n,pass:t});g.updateString(b);k=g.doFinal();return r==k}else{if(n.indexOf("withECDSA")!=-1){var f=null;try{f=KJUR.crypto.ECDSA.concatSigToASN1Sig(r)}catch(o){return false}var e=new KJUR.crypto.Signature({alg:n});e.init(t);e.updateString(b);return e.verify(f)}else{var e=new KJUR.crypto.Signature({alg:n});e.init(t);e.updateString(b);return e.verify(r)}}}};KJUR.jws.JWS.parse=function(g){var c=g.split(".");var b={};var f,e,d;if(c.length!=2&&c.length!=3){throw"malformed sJWS: wrong number of '.' splitted elements"}f=c[0];e=c[1];if(c.length==3){d=c[2]}b.headerObj=KJUR.jws.JWS.readSafeJSONString(b64utoutf8(f));b.payloadObj=KJUR.jws.JWS.readSafeJSONString(b64utoutf8(e));b.headerPP=JSON.stringify(b.headerObj,null," ");if(b.payloadObj==null){b.payloadPP=b64utoutf8(e)}else{b.payloadPP=JSON.stringify(b.payloadObj,null," ")}if(d!==undefined){b.sigHex=b64utohex(d)}return b};KJUR.jws.JWS.verifyJWT=function(d,j,l){var h=KJUR.jws.JWS;var i=d.split(".");var c=i[0];var g=i[1];var m=c+"."+g;var k=b64utohex(i[2]);var f=h.readSafeJSONString(b64utoutf8(c));var e=h.readSafeJSONString(b64utoutf8(g));if(f.alg===undefined){return false}if(l.alg===undefined){throw"acceptField.alg shall be specified"}if(!h.inArray(f.alg,l.alg)){return false}if(e.iss!==undefined&&typeof l.iss==="object"){if(!h.inArray(e.iss,l.iss)){return false}}if(e.sub!==undefined&&typeof l.sub==="object"){if(!h.inArray(e.sub,l.sub)){return false}}if(e.aud!==undefined&&typeof l.aud==="object"){if(typeof e.aud=="string"){if(!h.inArray(e.aud,l.aud)){return false}}else{if(typeof e.aud=="object"){if(!h.includedArray(e.aud,l.aud)){return false}}}}var b=KJUR.jws.IntDate.getNow();if(l.verifyAt!==undefined&&typeof l.verifyAt=="number"){b=l.verifyAt}if(e.exp!==undefined&&typeof e.exp=="number"){if(e.exp0){var c=":"+j.join(":")+":";if(c.indexOf(":"+h+":")==-1){throw"algorithm '"+h+"' not accepted in the list"}}if(h!="none"&&t===null){throw"key shall be specified to verify."}if(typeof t=="string"&&t.indexOf("-----BEGIN ")!=-1){t=KEYUTIL.getKey(t)}if(s=="RS"||s=="PS"){if(!(t instanceof RSAKey)){throw"key shall be a RSAKey obj for RS* and PS* algs"}}if(s=="ES"){if(!(t instanceof KJUR.crypto.ECDSA)){throw"key shall be a ECDSA obj for ES* algs"}}if(h=="none"){}var n=null;if(m.jwsalg2sigalg[i.alg]===undefined){throw"unsupported alg name: "+h}else{n=m.jwsalg2sigalg[h]}if(n=="none"){throw"not supported"}else{if(n.substr(0,4)=="Hmac"){var k=null;if(t===undefined){throw"hexadecimal key shall be specified for HMAC"}var g=new KJUR.crypto.Mac({alg:n,pass:t});g.updateString(b);k=g.doFinal();return r==k}else{if(n.indexOf("withECDSA")!=-1){var f=null;try{f=KJUR.crypto.ECDSA.concatSigToASN1Sig(r)}catch(o){return false}var e=new KJUR.crypto.Signature({alg:n});e.init(t);e.updateString(b);return e.verify(f)}else{var e=new KJUR.crypto.Signature({alg:n});e.init(t);e.updateString(b);return e.verify(r)}}}};KJUR.jws.JWS.parse=function(g){var c=g.split(".");var b={};var f,e,d;if(c.length!=2&&c.length!=3){throw"malformed sJWS: wrong number of '.' splitted elements"}f=c[0];e=c[1];if(c.length==3){d=c[2]}b.headerObj=KJUR.jws.JWS.readSafeJSONString(b64utoutf8(f));b.payloadObj=KJUR.jws.JWS.readSafeJSONString(b64utoutf8(e));b.headerPP=JSON.stringify(b.headerObj,null," ");if(b.payloadObj==null){b.payloadPP=b64utoutf8(e)}else{b.payloadPP=JSON.stringify(b.payloadObj,null," ")}if(d!==undefined){b.sigHex=b64utohex(d)}return b};KJUR.jws.JWS.verifyJWT=function(d,j,l){var h=KJUR.jws.JWS;var i=d.split(".");var c=i[0];var g=i[1];var m=c+"."+g;var k=b64utohex(i[2]);var f=h.readSafeJSONString(b64utoutf8(c));var e=h.readSafeJSONString(b64utoutf8(g));if(f.alg===undefined){return false}if(l.alg===undefined){throw"acceptField.alg shall be specified"}if(!h.inArray(f.alg,l.alg)){return false}if(e.iss!==undefined&&typeof l.iss==="object"){if(!h.inArray(e.iss,l.iss)){return false}}if(e.sub!==undefined&&typeof l.sub==="object"){if(!h.inArray(e.sub,l.sub)){return false}}if(e.aud!==undefined&&typeof l.aud==="object"){if(typeof e.aud=="string"){if(!h.inArray(e.aud,l.aud)){return false}}else{if(typeof e.aud=="object"){if(!h.includedArray(e.aud,l.aud)){return false}}}}var b=KJUR.jws.IntDate.getNow();if(l.verifyAt!==undefined&&typeof l.verifyAt==="number"){b=l.verifyAt}if(l.gracePeriod===undefined||typeof l.gracePeriod!=="number"){l.gracePeriod=0}if(e.exp!==undefined&&typeof e.exp=="number"){if(e.exp+l.gracePeriodMIT License */ @@ -537,6 +537,7 @@ KJUR.jws.JWS.parse = function(sJWS) { * @param {Array} acceptField associative array of acceptable fields (OPTION) * @return {Boolean} true if the JWT token is valid otherwise false * @since jws 3.2.3 jsrsasign 4.8.0 + * * @description * This method verifies a * RFC 7519 @@ -556,11 +557,22 @@ KJUR.jws.JWS.parse = function(sJWS) { * the same as value if specified. (OPTION) *
  • Time validity *
      - *
    • If acceptField.verifyAt as number of UNIX origin time is specifed for validation time, - * this method will verify at the time for it, otherwise current time will be used to verify.
    • - *
    • Payload.exp (expire) - Validation time is smaller than Payloead.exp.
    • - *
    • Payload.nbf (not before) - Validation time is greater than Payloead.nbf.
    • - *
    • Payload.iat (issued at) - Validation time is greater than Payloead.iat.
    • + *
    • + * If acceptField.verifyAt as number of UNIX origin time is specifed for validation time, + * this method will verify at the time for it, otherwise current time will be used to verify. + *
    • + *
    • + * Clock of JWT generator or verifier can be fast or slow. If these clocks are + * very different, JWT validation may fail. To avoid such case, 'jsrsasign' supports + * 'acceptField.gracePeriod' parameter which specifies acceptable time difference + * of those clocks in seconds. So if you want to accept slow or fast in 2 hours, + * you can specify acceptField.gracePeriod = 2 * 60 * 60;. + * "gracePeriod" is zero by default. + * "gracePeriod" is supported since jsrsasign 5.0.12. + *
    • + *
    • Payload.exp (expire) - Validation time is smaller than Payload.exp + gracePeriod.
    • + *
    • Payload.nbf (not before) - Validation time is greater than Payload.nbf - gracePeriod.
    • + *
    • Payload.iat (issued at) - Validation time is greater than Payload.iat - gracePeriod.
    • *
    *
  • *
  • Payload.jti (JWT id) - Payload.jti is included in acceptField.jti if specified. (OPTION)
  • @@ -579,7 +591,8 @@ KJUR.jws.JWS.parse = function(sJWS) { * sub: ['mailto:john@foo.com', 'mailto:alice@foo.com'], * verifyAt: KJUR.jws.IntDate.get('20150520235959Z'), * aud: ['http://foo.com'], // aud: 'http://foo.com' is fine too. - * jti: 'id123456' + * jti: 'id123456', + * gracePeriod: 1 * 60 * 60 // accept 1 hour slow or fast * }); */ KJUR.jws.JWS.verifyJWT = function(sJWT, key, acceptField) { @@ -625,25 +638,30 @@ KJUR.jws.JWS.verifyJWT = function(sJWT, key, acceptField) { } } - // 8. time validity (nbf < now < exp) && (iat <= now) + // 8. time validity + // (nbf - gracePeriod < now < exp + gracePeriod) && (iat - gracePeriod < now) var now = KJUR.jws.IntDate.getNow(); - if (acceptField.verifyAt !== undefined && typeof acceptField.verifyAt == "number") { + if (acceptField.verifyAt !== undefined && typeof acceptField.verifyAt === "number") { now = acceptField.verifyAt; } + if (acceptField.gracePeriod === undefined || + typeof acceptField.gracePeriod !== "number") { + acceptField.gracePeriod = 0; + } // 8.1 expired time 'exp' check if (pPayload.exp !== undefined && typeof pPayload.exp == "number") { - if (pPayload.exp < now) return false; + if (pPayload.exp + acceptField.gracePeriod < now) return false; } // 8.2 not before time 'nbf' check if (pPayload.nbf !== undefined && typeof pPayload.nbf == "number") { - if (now < pPayload.nbf) return false; + if (now < pPayload.nbf - acceptField.gracePeriod) return false; } // 8.3 issued at time 'iat' check if (pPayload.iat !== undefined && typeof pPayload.iat == "number") { - if (now < pPayload.iat) return false; + if (now < pPayload.iat - acceptField.gracePeriod) return false; } // 9 JWT id 'jti' check diff --git a/min/jws-3.3.min.js b/min/jws-3.3.min.js index 145229f0..1cda3ecb 100644 --- a/min/jws-3.3.min.js +++ b/min/jws-3.3.min.js @@ -1,3 +1,3 @@ -/*! jws-3.3.3 (c) 2013-2015 Kenji Urushima | kjur.github.com/jsrsasign/license +/*! jws-3.3.4 (c) 2013-2016 Kenji Urushima | kjur.github.com/jsrsasign/license */ -if(typeof KJUR=="undefined"||!KJUR){KJUR={}}if(typeof KJUR.jws=="undefined"||!KJUR.jws){KJUR.jws={}}KJUR.jws.JWS=function(){var a=KJUR.jws.JWS;this.parseJWS=function(e,g){if((this.parsedJWS!==undefined)&&(g||(this.parsedJWS.sigvalH!==undefined))){return}if(e.match(/^([^.]+)\.([^.]+)\.([^.]+)$/)==null){throw"JWS signature is not a form of 'Head.Payload.SigValue'."}var h=RegExp.$1;var c=RegExp.$2;var i=RegExp.$3;var k=h+"."+c;this.parsedJWS={};this.parsedJWS.headB64U=h;this.parsedJWS.payloadB64U=c;this.parsedJWS.sigvalB64U=i;this.parsedJWS.si=k;if(!g){var f=b64utohex(i);var d=parseBigInt(f,16);this.parsedJWS.sigvalH=f;this.parsedJWS.sigvalBI=d}var b=b64utoutf8(h);var j=b64utoutf8(c);this.parsedJWS.headS=b;this.parsedJWS.payloadS=j;if(!a.isSafeJSONString(b,this.parsedJWS,"headP")){throw"malformed JSON string for JWS Head: "+b}}};KJUR.jws.JWS.sign=function(a,i,c,m,l){var k=KJUR.jws.JWS;var q,e,j;if(typeof i!="string"&&typeof i!="object"){throw"spHeader must be JSON string or object: "+i}if(typeof i=="object"){e=i;q=JSON.stringify(e)}if(typeof i=="string"){q=i;if(!k.isSafeJSONString(q)){throw"JWS Head is not safe JSON string: "+q}e=k.readSafeJSONString(q)}j=c;if(typeof c=="object"){j=JSON.stringify(c)}if((a==""||a==null)&&e.alg!==undefined){a=e.alg}if((a!=""&&a!=null)&&e.alg===undefined){e.alg=a;q=JSON.stringify(e)}if(a!==e.alg){throw"alg and sHeader.alg doesn't match: "+a+"!="+e.alg}var d=null;if(k.jwsalg2sigalg[a]===undefined){throw"unsupported alg name: "+a}else{d=k.jwsalg2sigalg[a]}var b=utf8tob64u(q);var g=utf8tob64u(j);var o=b+"."+g;var n="";if(d.substr(0,4)=="Hmac"){if(m===undefined){throw"mac key shall be specified for HS* alg"}var h=new KJUR.crypto.Mac({alg:d,prov:"cryptojs",pass:m});h.updateString(o);n=h.doFinal()}else{if(d.indexOf("withECDSA")!=-1){var p=new KJUR.crypto.Signature({alg:d});p.init(m,l);p.updateString(o);hASN1Sig=p.sign();n=KJUR.crypto.ECDSA.asn1SigToConcatSig(hASN1Sig)}else{if(d!="none"){var p=new KJUR.crypto.Signature({alg:d});p.init(m,l);p.updateString(o);n=p.sign()}}}var f=hextob64u(n);return o+"."+f};KJUR.jws.JWS.verify=function(p,t,j){var m=KJUR.jws.JWS;var q=p.split(".");var d=q[0];var l=q[1];var b=d+"."+l;var r=b64utohex(q[2]);var i=m.readSafeJSONString(b64utoutf8(q[0]));var h=null;var s=null;if(i.alg===undefined){throw"algorithm not specified in header"}else{h=i.alg;s=h.substr(0,2)}if(j!=null&&Object.prototype.toString.call(j)==="[object Array]"&&j.length>0){var c=":"+j.join(":")+":";if(c.indexOf(":"+h+":")==-1){throw"algorithm '"+h+"' not accepted in the list"}}if(h!="none"&&t===null){throw"key shall be specified to verify."}if(typeof t=="string"&&t.indexOf("-----BEGIN ")!=-1){t=KEYUTIL.getKey(t)}if(s=="RS"||s=="PS"){if(!(t instanceof RSAKey)){throw"key shall be a RSAKey obj for RS* and PS* algs"}}if(s=="ES"){if(!(t instanceof KJUR.crypto.ECDSA)){throw"key shall be a ECDSA obj for ES* algs"}}if(h=="none"){}var n=null;if(m.jwsalg2sigalg[i.alg]===undefined){throw"unsupported alg name: "+h}else{n=m.jwsalg2sigalg[h]}if(n=="none"){throw"not supported"}else{if(n.substr(0,4)=="Hmac"){var k=null;if(t===undefined){throw"hexadecimal key shall be specified for HMAC"}var g=new KJUR.crypto.Mac({alg:n,pass:t});g.updateString(b);k=g.doFinal();return r==k}else{if(n.indexOf("withECDSA")!=-1){var f=null;try{f=KJUR.crypto.ECDSA.concatSigToASN1Sig(r)}catch(o){return false}var e=new KJUR.crypto.Signature({alg:n});e.init(t);e.updateString(b);return e.verify(f)}else{var e=new KJUR.crypto.Signature({alg:n});e.init(t);e.updateString(b);return e.verify(r)}}}};KJUR.jws.JWS.parse=function(g){var c=g.split(".");var b={};var f,e,d;if(c.length!=2&&c.length!=3){throw"malformed sJWS: wrong number of '.' splitted elements"}f=c[0];e=c[1];if(c.length==3){d=c[2]}b.headerObj=KJUR.jws.JWS.readSafeJSONString(b64utoutf8(f));b.payloadObj=KJUR.jws.JWS.readSafeJSONString(b64utoutf8(e));b.headerPP=JSON.stringify(b.headerObj,null," ");if(b.payloadObj==null){b.payloadPP=b64utoutf8(e)}else{b.payloadPP=JSON.stringify(b.payloadObj,null," ")}if(d!==undefined){b.sigHex=b64utohex(d)}return b};KJUR.jws.JWS.verifyJWT=function(d,j,l){var h=KJUR.jws.JWS;var i=d.split(".");var c=i[0];var g=i[1];var m=c+"."+g;var k=b64utohex(i[2]);var f=h.readSafeJSONString(b64utoutf8(c));var e=h.readSafeJSONString(b64utoutf8(g));if(f.alg===undefined){return false}if(l.alg===undefined){throw"acceptField.alg shall be specified"}if(!h.inArray(f.alg,l.alg)){return false}if(e.iss!==undefined&&typeof l.iss==="object"){if(!h.inArray(e.iss,l.iss)){return false}}if(e.sub!==undefined&&typeof l.sub==="object"){if(!h.inArray(e.sub,l.sub)){return false}}if(e.aud!==undefined&&typeof l.aud==="object"){if(typeof e.aud=="string"){if(!h.inArray(e.aud,l.aud)){return false}}else{if(typeof e.aud=="object"){if(!h.includedArray(e.aud,l.aud)){return false}}}}var b=KJUR.jws.IntDate.getNow();if(l.verifyAt!==undefined&&typeof l.verifyAt=="number"){b=l.verifyAt}if(e.exp!==undefined&&typeof e.exp=="number"){if(e.exp0){var c=":"+j.join(":")+":";if(c.indexOf(":"+h+":")==-1){throw"algorithm '"+h+"' not accepted in the list"}}if(h!="none"&&t===null){throw"key shall be specified to verify."}if(typeof t=="string"&&t.indexOf("-----BEGIN ")!=-1){t=KEYUTIL.getKey(t)}if(s=="RS"||s=="PS"){if(!(t instanceof RSAKey)){throw"key shall be a RSAKey obj for RS* and PS* algs"}}if(s=="ES"){if(!(t instanceof KJUR.crypto.ECDSA)){throw"key shall be a ECDSA obj for ES* algs"}}if(h=="none"){}var n=null;if(m.jwsalg2sigalg[i.alg]===undefined){throw"unsupported alg name: "+h}else{n=m.jwsalg2sigalg[h]}if(n=="none"){throw"not supported"}else{if(n.substr(0,4)=="Hmac"){var k=null;if(t===undefined){throw"hexadecimal key shall be specified for HMAC"}var g=new KJUR.crypto.Mac({alg:n,pass:t});g.updateString(b);k=g.doFinal();return r==k}else{if(n.indexOf("withECDSA")!=-1){var f=null;try{f=KJUR.crypto.ECDSA.concatSigToASN1Sig(r)}catch(o){return false}var e=new KJUR.crypto.Signature({alg:n});e.init(t);e.updateString(b);return e.verify(f)}else{var e=new KJUR.crypto.Signature({alg:n});e.init(t);e.updateString(b);return e.verify(r)}}}};KJUR.jws.JWS.parse=function(g){var c=g.split(".");var b={};var f,e,d;if(c.length!=2&&c.length!=3){throw"malformed sJWS: wrong number of '.' splitted elements"}f=c[0];e=c[1];if(c.length==3){d=c[2]}b.headerObj=KJUR.jws.JWS.readSafeJSONString(b64utoutf8(f));b.payloadObj=KJUR.jws.JWS.readSafeJSONString(b64utoutf8(e));b.headerPP=JSON.stringify(b.headerObj,null," ");if(b.payloadObj==null){b.payloadPP=b64utoutf8(e)}else{b.payloadPP=JSON.stringify(b.payloadObj,null," ")}if(d!==undefined){b.sigHex=b64utohex(d)}return b};KJUR.jws.JWS.verifyJWT=function(d,j,l){var h=KJUR.jws.JWS;var i=d.split(".");var c=i[0];var g=i[1];var m=c+"."+g;var k=b64utohex(i[2]);var f=h.readSafeJSONString(b64utoutf8(c));var e=h.readSafeJSONString(b64utoutf8(g));if(f.alg===undefined){return false}if(l.alg===undefined){throw"acceptField.alg shall be specified"}if(!h.inArray(f.alg,l.alg)){return false}if(e.iss!==undefined&&typeof l.iss==="object"){if(!h.inArray(e.iss,l.iss)){return false}}if(e.sub!==undefined&&typeof l.sub==="object"){if(!h.inArray(e.sub,l.sub)){return false}}if(e.aud!==undefined&&typeof l.aud==="object"){if(typeof e.aud=="string"){if(!h.inArray(e.aud,l.aud)){return false}}else{if(typeof e.aud=="object"){if(!h.includedArray(e.aud,l.aud)){return false}}}}var b=KJUR.jws.IntDate.getNow();if(l.verifyAt!==undefined&&typeof l.verifyAt==="number"){b=l.verifyAt}if(l.gracePeriod===undefined||typeof l.gracePeriod!=="number"){l.gracePeriod=0}if(e.exp!==undefined&&typeof e.exp=="number"){if(e.exp+l.gracePeriod0){var c=":"+j.join(":")+":";if(c.indexOf(":"+h+":")==-1){throw"algorithm '"+h+"' not accepted in the list"}}if(h!="none"&&t===null){throw"key shall be specified to verify."}if(typeof t=="string"&&t.indexOf("-----BEGIN ")!=-1){t=KEYUTIL.getKey(t)}if(s=="RS"||s=="PS"){if(!(t instanceof RSAKey)){throw"key shall be a RSAKey obj for RS* and PS* algs"}}if(s=="ES"){if(!(t instanceof KJUR.crypto.ECDSA)){throw"key shall be a ECDSA obj for ES* algs"}}if(h=="none"){}var n=null;if(m.jwsalg2sigalg[i.alg]===undefined){throw"unsupported alg name: "+h}else{n=m.jwsalg2sigalg[h]}if(n=="none"){throw"not supported"}else{if(n.substr(0,4)=="Hmac"){var k=null;if(t===undefined){throw"hexadecimal key shall be specified for HMAC"}var g=new KJUR.crypto.Mac({alg:n,pass:t});g.updateString(b);k=g.doFinal();return r==k}else{if(n.indexOf("withECDSA")!=-1){var f=null;try{f=KJUR.crypto.ECDSA.concatSigToASN1Sig(r)}catch(o){return false}var e=new KJUR.crypto.Signature({alg:n});e.init(t);e.updateString(b);return e.verify(f)}else{var e=new KJUR.crypto.Signature({alg:n});e.init(t);e.updateString(b);return e.verify(r)}}}};KJUR.jws.JWS.parse=function(g){var c=g.split(".");var b={};var f,e,d;if(c.length!=2&&c.length!=3){throw"malformed sJWS: wrong number of '.' splitted elements"}f=c[0];e=c[1];if(c.length==3){d=c[2]}b.headerObj=KJUR.jws.JWS.readSafeJSONString(b64utoutf8(f));b.payloadObj=KJUR.jws.JWS.readSafeJSONString(b64utoutf8(e));b.headerPP=JSON.stringify(b.headerObj,null," ");if(b.payloadObj==null){b.payloadPP=b64utoutf8(e)}else{b.payloadPP=JSON.stringify(b.payloadObj,null," ")}if(d!==undefined){b.sigHex=b64utohex(d)}return b};KJUR.jws.JWS.verifyJWT=function(d,j,l){var h=KJUR.jws.JWS;var i=d.split(".");var c=i[0];var g=i[1];var m=c+"."+g;var k=b64utohex(i[2]);var f=h.readSafeJSONString(b64utoutf8(c));var e=h.readSafeJSONString(b64utoutf8(g));if(f.alg===undefined){return false}if(l.alg===undefined){throw"acceptField.alg shall be specified"}if(!h.inArray(f.alg,l.alg)){return false}if(e.iss!==undefined&&typeof l.iss==="object"){if(!h.inArray(e.iss,l.iss)){return false}}if(e.sub!==undefined&&typeof l.sub==="object"){if(!h.inArray(e.sub,l.sub)){return false}}if(e.aud!==undefined&&typeof l.aud==="object"){if(typeof e.aud=="string"){if(!h.inArray(e.aud,l.aud)){return false}}else{if(typeof e.aud=="object"){if(!h.includedArray(e.aud,l.aud)){return false}}}}var b=KJUR.jws.IntDate.getNow();if(l.verifyAt!==undefined&&typeof l.verifyAt=="number"){b=l.verifyAt}if(e.exp!==undefined&&typeof e.exp=="number"){if(e.exp0){var c=":"+j.join(":")+":";if(c.indexOf(":"+h+":")==-1){throw"algorithm '"+h+"' not accepted in the list"}}if(h!="none"&&t===null){throw"key shall be specified to verify."}if(typeof t=="string"&&t.indexOf("-----BEGIN ")!=-1){t=KEYUTIL.getKey(t)}if(s=="RS"||s=="PS"){if(!(t instanceof RSAKey)){throw"key shall be a RSAKey obj for RS* and PS* algs"}}if(s=="ES"){if(!(t instanceof KJUR.crypto.ECDSA)){throw"key shall be a ECDSA obj for ES* algs"}}if(h=="none"){}var n=null;if(m.jwsalg2sigalg[i.alg]===undefined){throw"unsupported alg name: "+h}else{n=m.jwsalg2sigalg[h]}if(n=="none"){throw"not supported"}else{if(n.substr(0,4)=="Hmac"){var k=null;if(t===undefined){throw"hexadecimal key shall be specified for HMAC"}var g=new KJUR.crypto.Mac({alg:n,pass:t});g.updateString(b);k=g.doFinal();return r==k}else{if(n.indexOf("withECDSA")!=-1){var f=null;try{f=KJUR.crypto.ECDSA.concatSigToASN1Sig(r)}catch(o){return false}var e=new KJUR.crypto.Signature({alg:n});e.init(t);e.updateString(b);return e.verify(f)}else{var e=new KJUR.crypto.Signature({alg:n});e.init(t);e.updateString(b);return e.verify(r)}}}};KJUR.jws.JWS.parse=function(g){var c=g.split(".");var b={};var f,e,d;if(c.length!=2&&c.length!=3){throw"malformed sJWS: wrong number of '.' splitted elements"}f=c[0];e=c[1];if(c.length==3){d=c[2]}b.headerObj=KJUR.jws.JWS.readSafeJSONString(b64utoutf8(f));b.payloadObj=KJUR.jws.JWS.readSafeJSONString(b64utoutf8(e));b.headerPP=JSON.stringify(b.headerObj,null," ");if(b.payloadObj==null){b.payloadPP=b64utoutf8(e)}else{b.payloadPP=JSON.stringify(b.payloadObj,null," ")}if(d!==undefined){b.sigHex=b64utohex(d)}return b};KJUR.jws.JWS.verifyJWT=function(d,j,l){var h=KJUR.jws.JWS;var i=d.split(".");var c=i[0];var g=i[1];var m=c+"."+g;var k=b64utohex(i[2]);var f=h.readSafeJSONString(b64utoutf8(c));var e=h.readSafeJSONString(b64utoutf8(g));if(f.alg===undefined){return false}if(l.alg===undefined){throw"acceptField.alg shall be specified"}if(!h.inArray(f.alg,l.alg)){return false}if(e.iss!==undefined&&typeof l.iss==="object"){if(!h.inArray(e.iss,l.iss)){return false}}if(e.sub!==undefined&&typeof l.sub==="object"){if(!h.inArray(e.sub,l.sub)){return false}}if(e.aud!==undefined&&typeof l.aud==="object"){if(typeof e.aud=="string"){if(!h.inArray(e.aud,l.aud)){return false}}else{if(typeof e.aud=="object"){if(!h.includedArray(e.aud,l.aud)){return false}}}}var b=KJUR.jws.IntDate.getNow();if(l.verifyAt!==undefined&&typeof l.verifyAt==="number"){b=l.verifyAt}if(l.gracePeriod===undefined||typeof l.gracePeriod!=="number"){l.gracePeriod=0}if(e.exp!==undefined&&typeof e.exp=="number"){if(e.exp+l.gracePeriod - +