/*! jws-3.2.2 (c) 2013-2015 Kenji Urushima | kjur.github.com/jsjws/license */ /* * jws.js - JSON Web Signature Class * * version: 3.2.2 (2015 Apr 26) * * Copyright (c) 2010-2015 Kenji Urushima (kenji.urushima@gmail.com) * * This software is licensed under the terms of the MIT License. * http://kjur.github.com/jsjws/license/ * * The above copyright and license notice shall be * included in all copies or substantial portions of the Software. */ /** * @fileOverview * @name jws-3.2.js * @author Kenji Urushima kenji.urushima@gmail.com * @version 3.2.2 (2015-Apr-26) * @since jsjws 1.0 * @license MIT License */ if (typeof KJUR == "undefined" || !KJUR) KJUR = {}; if (typeof KJUR.jws == "undefined" || !KJUR.jws) KJUR.jws = {}; /** * JSON Web Signature(JWS) class.
* @name KJUR.jws.JWS * @class JSON Web Signature(JWS) class * @property {Dictionary} parsedJWS This property is set after JWS signature verification.
* Following "parsedJWS_*" properties can be accessed as "parsedJWS.*" because of * JsDoc restriction. * @property {String} parsedJWS_headB64U string of Encrypted JWS Header * @property {String} parsedJWS_payloadB64U string of Encrypted JWS Payload * @property {String} parsedJWS_sigvalB64U string of Encrypted JWS signature value * @property {String} parsedJWS_si string of Signature Input * @property {String} parsedJWS_sigvalH hexadecimal string of JWS signature value * @property {String} parsedJWS_sigvalBI BigInteger(defined in jsbn.js) object of JWS signature value * @property {String} parsedJWS_headS string of decoded JWS Header * @property {String} parsedJWS_headS string of decoded JWS Payload * @requires base64x.js, json-sans-eval.js and jsrsasign library * @see 'jwjws'(JWS JavaScript Library) home page http://kjur.github.com/jsjws/ * @see 'jwrsasign'(RSA Sign JavaScript Library) home page http://kjur.github.com/jsrsasign/ * @see IETF I-D JSON Web Algorithms (JWA) * @since jsjws 1.0 * @description *

Supported Algorithms

* Here is supported algorithm names for {@link KJUR.jws.JWS.sign} and {@link KJUR.jws.JWS.verify} * methods. * * * * * * * * * * * * * * * *
alg valuespec requirementjsjws support
HS256REQUIREDSUPPORTED
HS384OPTIONALSUPPORTED
HS512OPTIONALSUPPORTED
RS256RECOMMENDEDSUPPORTED
RS384OPTIONALSUPPORTED
RS512OPTIONALSUPPORTED
ES256RECOMMENDED+SUPPORTED
ES384OPTIONALSUPPORTED
ES512OPTIONAL-
PS256OPTIONALSUPPORTED
PS384OPTIONALSUPPORTED
PS512OPTIONALSUPPORTED
noneREQUIREDSUPPORTED(signature generation only)
* NOTE1: HS384 is supported since jsjws 3.0.2 with jsrsasign 4.1.4.
*/ KJUR.jws.JWS = function() { var ns1 = KJUR.jws.JWS; // === utility ============================================================= /** * parse JWS string and set public property 'parsedJWS' dictionary.
* @name parseJWS * @memberOf KJUR.jws.JWS * @function * @param {String} sJWS JWS signature string to be parsed. * @throws if sJWS is not comma separated string such like "Header.Payload.Signature". * @throws if JWS Header is a malformed JSON string. * @since jws 1.1 */ this.parseJWS = function(sJWS, sigValNotNeeded) { if ((this.parsedJWS !== undefined) && (sigValNotNeeded || (this.parsedJWS.sigvalH !== undefined))) { return; } if (sJWS.match(/^([^.]+)\.([^.]+)\.([^.]+)$/) == null) { throw "JWS signature is not a form of 'Head.Payload.SigValue'."; } var b6Head = RegExp.$1; var b6Payload = RegExp.$2; var b6SigVal = RegExp.$3; var sSI = b6Head + "." + b6Payload; this.parsedJWS = {}; this.parsedJWS.headB64U = b6Head; this.parsedJWS.payloadB64U = b6Payload; this.parsedJWS.sigvalB64U = b6SigVal; this.parsedJWS.si = sSI; if (!sigValNotNeeded) { var hSigVal = b64utohex(b6SigVal); var biSigVal = parseBigInt(hSigVal, 16); this.parsedJWS.sigvalH = hSigVal; this.parsedJWS.sigvalBI = biSigVal; } var sHead = b64utoutf8(b6Head); var sPayload = b64utoutf8(b6Payload); this.parsedJWS.headS = sHead; this.parsedJWS.payloadS = sPayload; if (! ns1.isSafeJSONString(sHead, this.parsedJWS, 'headP')) throw "malformed JSON string for JWS Head: " + sHead; }; // ==== JWS Validation ========================================================= function _getSignatureInputByString(sHead, sPayload) { return utf8tob64u(sHead) + "." + utf8tob64u(sPayload); }; function _getHashBySignatureInput(sSignatureInput, sHashAlg) { var hashfunc = function(s) { return KJUR.crypto.Util.hashString(s, sHashAlg); }; if (hashfunc == null) throw "hash function not defined in jsrsasign: " + sHashAlg; return hashfunc(sSignatureInput); }; function _jws_verifySignature(sHead, sPayload, hSig, hN, hE) { var sSignatureInput = _getSignatureInputByString(sHead, sPayload); var biSig = parseBigInt(hSig, 16); return _rsasign_verifySignatureWithArgs(sSignatureInput, biSig, hN, hE); }; /** * verify JWS signature with naked RSA public key.
* This only supports "RS256" and "RS512" algorithm. * @name verifyJWSByNE * @memberOf KJUR.jws.JWS * @function * @param {String} sJWS JWS signature string to be verified * @param {String} hN hexadecimal string for modulus of RSA public key * @param {String} hE hexadecimal string for public exponent of RSA public key * @return {String} returns 1 when JWS signature is valid, otherwise returns 0 * @throws if sJWS is not comma separated string such like "Header.Payload.Signature". * @throws if JWS Header is a malformed JSON string. * @deprecated from 3.0.0 please move to {@link KJUR.jws.JWS.verify} */ this.verifyJWSByNE = function(sJWS, hN, hE) { this.parseJWS(sJWS); return _rsasign_verifySignatureWithArgs(this.parsedJWS.si, this.parsedJWS.sigvalBI, hN, hE); }; /** * verify JWS signature with RSA public key.
* This only supports "RS256", "RS512", "PS256" and "PS512" algorithms. * @name verifyJWSByKey * @memberOf KJUR.jws.JWS * @function * @param {String} sJWS JWS signature string to be verified * @param {RSAKey} key RSA public key * @return {Boolean} returns true when JWS signature is valid, otherwise returns false * @throws if sJWS is not comma separated string such like "Header.Payload.Signature". * @throws if JWS Header is a malformed JSON string. * @deprecated from 3.0.0 please move to {@link KJUR.jws.JWS.verify} */ this.verifyJWSByKey = function(sJWS, key) { this.parseJWS(sJWS); var hashAlg = _jws_getHashAlgFromParsedHead(this.parsedJWS.headP); var isPSS = this.parsedJWS.headP['alg'].substr(0, 2) == "PS"; if (key.hashAndVerify) { return key.hashAndVerify(hashAlg, new Buffer(this.parsedJWS.si, 'utf8').toString('base64'), b64utob64(this.parsedJWS.sigvalB64U), 'base64', isPSS); } else if (isPSS) { return key.verifyStringPSS(this.parsedJWS.si, this.parsedJWS.sigvalH, hashAlg); } else { return key.verifyString(this.parsedJWS.si, this.parsedJWS.sigvalH); } }; /** * verify JWS signature by PEM formatted X.509 certificate.
* This only supports "RS256" and "RS512" algorithm. * @name verifyJWSByPemX509Cert * @memberOf KJUR.jws.JWS * @function * @param {String} sJWS JWS signature string to be verified * @param {String} sPemX509Cert string of PEM formatted X.509 certificate * @return {String} returns 1 when JWS signature is valid, otherwise returns 0 * @throws if sJWS is not comma separated string such like "Header.Payload.Signature". * @throws if JWS Header is a malformed JSON string. * @since 1.1 * @deprecated from 3.0.0 please move to {@link KJUR.jws.JWS.verify} */ this.verifyJWSByPemX509Cert = function(sJWS, sPemX509Cert) { this.parseJWS(sJWS); var x509 = new X509(); x509.readCertPEM(sPemX509Cert); return x509.subjectPublicKeyRSA.verifyString(this.parsedJWS.si, this.parsedJWS.sigvalH); }; // ==== JWS Generation ========================================================= function _jws_getHashAlgFromParsedHead(head) { var sigAlg = head["alg"]; var hashAlg = ""; if (sigAlg != "RS256" && sigAlg != "RS512" && sigAlg != "PS256" && sigAlg != "PS512") throw "JWS signature algorithm not supported: " + sigAlg; if (sigAlg.substr(2) == "256") hashAlg = "sha256"; if (sigAlg.substr(2) == "512") hashAlg = "sha512"; return hashAlg; }; function _jws_getHashAlgFromHead(sHead) { return _jws_getHashAlgFromParsedHead(jsonParse(sHead)); }; function _jws_generateSignatureValueBySI_NED(sHead, sPayload, sSI, hN, hE, hD) { var rsa = new RSAKey(); rsa.setPrivate(hN, hE, hD); var hashAlg = _jws_getHashAlgFromHead(sHead); var sigValue = rsa.signString(sSI, hashAlg); return sigValue; }; function _jws_generateSignatureValueBySI_Key(sHead, sPayload, sSI, key, head) { var hashAlg = null; if (typeof head == "undefined") { hashAlg = _jws_getHashAlgFromHead(sHead); } else { hashAlg = _jws_getHashAlgFromParsedHead(head); } var isPSS = head['alg'].substr(0, 2) == "PS"; if (key.hashAndSign) { return b64tob64u(key.hashAndSign(hashAlg, sSI, 'binary', 'base64', isPSS)); } else if (isPSS) { return hextob64u(key.signStringPSS(sSI, hashAlg)); } else { return hextob64u(key.signString(sSI, hashAlg)); } }; function _jws_generateSignatureValueByNED(sHead, sPayload, hN, hE, hD) { var sSI = _getSignatureInputByString(sHead, sPayload); return _jws_generateSignatureValueBySI_NED(sHead, sPayload, sSI, hN, hE, hD); }; /** * generate JWS signature by Header, Payload and a naked RSA private key.
* This only supports "RS256" and "RS512" algorithm. * @name generateJWSByNED * @memberOf KJUR.jws.JWS * @function * @param {String} sHead string of JWS Header * @param {String} sPayload string of JWS Payload * @param {String} hN hexadecimal string for modulus of RSA public key * @param {String} hE hexadecimal string for public exponent of RSA public key * @param {String} hD hexadecimal string for private exponent of RSA private key * @return {String} JWS signature string * @throws if sHead is a malformed JSON string. * @throws if supported signature algorithm was not specified in JSON Header. * @deprecated from 3.0.0 please move to {@link KJUR.jws.JWS.sign} */ this.generateJWSByNED = function(sHead, sPayload, hN, hE, hD) { if (! ns1.isSafeJSONString(sHead)) throw "JWS Head is not safe JSON string: " + sHead; var sSI = _getSignatureInputByString(sHead, sPayload); var hSigValue = _jws_generateSignatureValueBySI_NED(sHead, sPayload, sSI, hN, hE, hD); var b64SigValue = hextob64u(hSigValue); this.parsedJWS = {}; this.parsedJWS.headB64U = sSI.split(".")[0]; this.parsedJWS.payloadB64U = sSI.split(".")[1]; this.parsedJWS.sigvalB64U = b64SigValue; return sSI + "." + b64SigValue; }; /** * generate JWS signature by Header, Payload and a RSA private key.
* This only supports "RS256", "RS512", "PS256" and "PS512" algorithms. * @name generateJWSByKey * @memberOf KJUR.jws.JWS * @function * @param {String} sHead string of JWS Header * @param {String} sPayload string of JWS Payload * @param {RSAKey} RSA private key * @return {String} JWS signature string * @throws if sHead is a malformed JSON string. * @throws if supported signature algorithm was not specified in JSON Header. * @deprecated from 3.0.0 please move to {@link KJUR.jws.JWS.sign} */ this.generateJWSByKey = function(sHead, sPayload, key) { var obj = {}; if (! ns1.isSafeJSONString(sHead, obj, 'headP')) throw "JWS Head is not safe JSON string: " + sHead; var sSI = _getSignatureInputByString(sHead, sPayload); var b64SigValue = _jws_generateSignatureValueBySI_Key(sHead, sPayload, sSI, key, obj.headP); this.parsedJWS = {}; this.parsedJWS.headB64U = sSI.split(".")[0]; this.parsedJWS.payloadB64U = sSI.split(".")[1]; this.parsedJWS.sigvalB64U = b64SigValue; return sSI + "." + b64SigValue; }; // === sign with PKCS#1 RSA private key ===================================================== function _jws_generateSignatureValueBySI_PemPrvKey(sHead, sPayload, sSI, sPemPrvKey) { var rsa = new RSAKey(); rsa.readPrivateKeyFromPEMString(sPemPrvKey); var hashAlg = _jws_getHashAlgFromHead(sHead); var sigValue = rsa.signString(sSI, hashAlg); return sigValue; }; /** * generate JWS signature by Header, Payload and a PEM formatted PKCS#1 RSA private key.
* This only supports "RS256" and "RS512" algorithm. * @name generateJWSByP1PrvKey * @memberOf KJUR.jws.JWS * @function * @param {String} sHead string of JWS Header * @param {String} sPayload string of JWS Payload * @param {String} string for sPemPrvKey PEM formatted PKCS#1 RSA private key
* Heading and trailing space characters in PEM key will be ignored. * @return {String} JWS signature string * @throws if sHead is a malformed JSON string. * @throws if supported signature algorithm was not specified in JSON Header. * @since 1.1 * @deprecated from 3.0.0 please move to {@link KJUR.jws.JWS.sign} */ this.generateJWSByP1PrvKey = function(sHead, sPayload, sPemPrvKey) { if (! ns1.isSafeJSONString(sHead)) throw "JWS Head is not safe JSON string: " + sHead; var sSI = _getSignatureInputByString(sHead, sPayload); var hSigValue = _jws_generateSignatureValueBySI_PemPrvKey(sHead, sPayload, sSI, sPemPrvKey); var b64SigValue = hextob64u(hSigValue); this.parsedJWS = {}; this.parsedJWS.headB64U = sSI.split(".")[0]; this.parsedJWS.payloadB64U = sSI.split(".")[1]; this.parsedJWS.sigvalB64U = b64SigValue; return sSI + "." + b64SigValue; }; }; // === major static method ======================================================== /** * generate JWS signature by specified key
* @name sign * @memberOf KJUR.jws.JWS * @function * @static * @param {String} alg JWS algorithm name to sign and force set to sHead or null * @param {String} sHead string of JWS Header * @param {String} sPayload string of JWS Payload * @param {String} key string of private key or key object to sign * @param {String} pass (OPTION)passcode to use encrypted private key * @return {String} JWS signature string * @since jws 3.0.0 * @see jsrsasign KJUR.crypto.Signature method * @see jsrsasign KJUR.crypto.Mac method * @description * This method supports following algorithms. * * * * * * * * * * * * * * * *
alg valuespec requirementjsjws support
HS256REQUIREDSUPPORTED
HS384OPTIONAL-
HS512OPTIONALSUPPORTED
RS256RECOMMENDEDSUPPORTED
RS384OPTIONALSUPPORTED
RS512OPTIONALSUPPORTED
ES256RECOMMENDED+SUPPORTED
ES384OPTIONALSUPPORTED
ES512OPTIONAL-
PS256OPTIONALSUPPORTED
PS384OPTIONALSUPPORTED
PS512OPTIONALSUPPORTED
noneREQUIREDSUPPORTED(signature generation only)
*
*
NOTE1: *
salt length of RSAPSS signature is the same as the hash algorithm length * because of IETF JOSE ML discussion. *
NOTE2: *
The reason of HS384 unsupport is * CryptoJS HmacSHA384 bug. *
*/ KJUR.jws.JWS.sign = function(alg, sHeader, sPayload, key, pass) { var ns1 = KJUR.jws.JWS; if (! ns1.isSafeJSONString(sHeader)) throw "JWS Head is not safe JSON string: " + sHeader; var pHeader = ns1.readSafeJSONString(sHeader); // 1. use alg if defined in sHeader if ((alg == '' || alg == null) && pHeader['alg'] !== undefined) { alg = pHeader['alg']; } // 2. set alg in sHeader if undefined if ((alg != '' && alg != null) && pHeader['alg'] === undefined) { pHeader['alg'] = alg; sHeader = JSON.stringify(pHeader); } // 3. set signature algorithm like SHA1withRSA var sigAlg = null; if (ns1.jwsalg2sigalg[alg] === undefined) { throw "unsupported alg name: " + alg; } else { sigAlg = ns1.jwsalg2sigalg[alg]; } var uHeader = utf8tob64u(sHeader); var uPayload = utf8tob64u(sPayload); var uSignatureInput = uHeader + "." + uPayload // 4. sign var hSig = ""; if (sigAlg.substr(0, 4) == "Hmac") { if (key === undefined) throw "hexadecimal key shall be specified for HMAC"; var mac = new KJUR.crypto.Mac({'alg': sigAlg, 'pass': hextorstr(key)}); mac.updateString(uSignatureInput); hSig = mac.doFinal(); } else if (sigAlg.indexOf("withECDSA") != -1) { var sig = new KJUR.crypto.Signature({'alg': sigAlg}); sig.init(key, pass); sig.updateString(uSignatureInput); hASN1Sig = sig.sign(); hSig = KJUR.crypto.ECDSA.asn1SigToConcatSig(hASN1Sig); } else if (sigAlg != "none") { var sig = new KJUR.crypto.Signature({'alg': sigAlg}); sig.init(key, pass); sig.updateString(uSignatureInput); hSig = sig.sign(); } var uSig = hextob64u(hSig); return uSignatureInput + "." + uSig; }; /** * verify JWS signature by specified key or certificate
* @name verify * @memberOf KJUR.jws.JWS * @function * @static * @param {String} sJWS string of JWS signature to verify * @param {Object} key string of public key, certificate or key object to verify * @param {String} acceptAlgs array of algorithm name strings (OPTION) * @return {Boolean} true if the signature is valid otherwise false * @since jws 3.0.0 * @see jsrsasign KJUR.crypto.Signature method * @see jsrsasign KJUR.crypto.Mac method * @description *

* This method verifies a JSON Web Signature Compact Serialization string by the validation * algorithm as described in * * the section 5 of Internet Draft draft-jones-json-web-signature-04. *

*

* Since 3.2.0 strict key checking has been provided against a JWS algorithm * in a JWS header. *

*

*

* NOTE1: The argument 'acceptAlgs' is supported since 3.2.0. * Strongly recommended to provide acceptAlgs to mitigate * signature replacement attacks.
*

* @example * // 1) verify a RS256 JWS signature by a certificate string. * var isValid = KJUR.jws.JWS.verify('eyJh...', '-----BEGIN...', ['RS256']); * * // 2) verify a HS256 JWS signature by a certificate string. * var isValid = KJUR.jws.JWS.verify('eyJh...', '6f62ad...', ['HS256']); * * // 3) verify a ES256 JWS signature by a KJUR.crypto.ECDSA key object. * var pubkey = KEYUTIL.getKey('-----BEGIN CERT...'); * var isValid = KJUR.jws.JWS.verify('eyJh...', pubkey); */ KJUR.jws.JWS.verify = function(sJWS, key, acceptAlgs) { var jws = KJUR.jws.JWS; var a = sJWS.split("."); var uHeader = a[0]; var uPayload = a[1]; var uSignatureInput = uHeader + "." + uPayload; var hSig = b64utohex(a[2]); // 1. parse JWS header var pHeader = jws.readSafeJSONString(b64utoutf8(a[0])); var alg = null; var algType = null; // HS|RS|PS|ES|no if (pHeader.alg === undefined) { throw "algorithm not specified in header"; } else { alg = pHeader.alg; algType = alg.substr(0, 2); } // 2. check whether alg is acceptable algorithms if (acceptAlgs != null && Object.prototype.toString.call(acceptAlgs) === '[object Array]' && acceptAlgs.length > 0) { var acceptAlgStr = ":" + acceptAlgs.join(":") + ":"; if (acceptAlgStr.indexOf(":" + alg + ":") == -1) { throw "algorithm '" + alg + "' not accepted in the list"; } } // 3. check whether key is a proper key for alg. if (alg != "none" && key === null) { throw "key shall be specified to verify."; } // 3.1. check whether key is hexstr if alg is HS*. if (algType == "HS") { if (typeof key != "string" && key.length != 0 && key.length % 2 != 0 && ! key.match(/^[0-9A-Fa-f]+/)) { throw "key shall be a hexadecimal str for HS* algs"; } } // 3.2. convert key object if key is a public key or cert PEM string if (typeof key == "string" && key.indexOf("-----BEGIN ") != -1) { key = KEYUTIL.getKey(key); } // 3.3. check whether key is RSAKey obj if alg is RS* or PS*. if (algType == "RS" || algType == "PS") { if (!(key instanceof RSAKey)) { throw "key shall be a RSAKey obj for RS* and PS* algs"; } } // 3.4. check whether key is ECDSA obj if alg is ES*. if (algType == "ES") { if (!(key instanceof KJUR.crypto.ECDSA)) { throw "key shall be a ECDSA obj for ES* algs"; } } // 3.5. check when alg is 'none' if (alg == "none") { } // 4. check whether alg is supported alg in jsjws. var sigAlg = null; if (jws.jwsalg2sigalg[pHeader.alg] === undefined) { throw "unsupported alg name: " + alg; } else { sigAlg = jws.jwsalg2sigalg[alg]; } // 5. verify if (sigAlg == "none") { throw "not supported"; } else if (sigAlg.substr(0, 4) == "Hmac") { if (key === undefined) throw "hexadecimal key shall be specified for HMAC"; var mac = new KJUR.crypto.Mac({'alg': sigAlg, 'pass': hextorstr(key)}); mac.updateString(uSignatureInput); hSig2 = mac.doFinal(); return hSig == hSig2; } else if (sigAlg.indexOf("withECDSA") != -1) { var hASN1Sig = null; try { hASN1Sig = KJUR.crypto.ECDSA.concatSigToASN1Sig(hSig); } catch (ex) { return false; } var sig = new KJUR.crypto.Signature({'alg': sigAlg}); sig.init(key) sig.updateString(uSignatureInput); return sig.verify(hASN1Sig); } else { var sig = new KJUR.crypto.Signature({'alg': sigAlg}); sig.init(key) sig.updateString(uSignatureInput); return sig.verify(hSig); } }; /* * @since jws 3.0.0 */ KJUR.jws.JWS.jwsalg2sigalg = { "HS256": "HmacSHA256", "HS384": "HmacSHA384", "HS512": "HmacSHA512", "RS256": "SHA256withRSA", "RS384": "SHA384withRSA", "RS512": "SHA512withRSA", "ES256": "SHA256withECDSA", "ES384": "SHA384withECDSA", //"ES512": "SHA512withECDSA", // unsupported because of jsrsasign's bug "PS256": "SHA256withRSAandMGF1", "PS384": "SHA384withRSAandMGF1", "PS512": "SHA512withRSAandMGF1", "none": "none", }; // === utility static method ====================================================== /** * check whether a String "s" is a safe JSON string or not.
* If a String "s" is a malformed JSON string or an other object type * this returns 0, otherwise this returns 1. * @name isSafeJSONString * @memberOf KJUR.jws.JWS * @function * @static * @param {String} s JSON string * @return {Number} 1 or 0 */ KJUR.jws.JWS.isSafeJSONString = function(s, h, p) { var o = null; try { o = jsonParse(s); if (typeof o != "object") return 0; if (o.constructor === Array) return 0; if (h) h[p] = o; return 1; } catch (ex) { return 0; } }; /** * read a String "s" as JSON object if it is safe.
* If a String "s" is a malformed JSON string or not JSON string, * this returns null, otherwise returns JSON object. * @name readSafeJSONString * @memberOf KJUR.jws.JWS * @function * @static * @param {String} s JSON string * @return {Object} JSON object or null * @since 1.1.1 */ KJUR.jws.JWS.readSafeJSONString = function(s) { var o = null; try { o = jsonParse(s); if (typeof o != "object") return null; if (o.constructor === Array) return null; return o; } catch (ex) { return null; } }; /** * get Encoed Signature Value from JWS string.
* @name getEncodedSignatureValueFromJWS * @memberOf KJUR.jws.JWS * @function * @static * @param {String} sJWS JWS signature string to be verified * @return {String} string of Encoded Signature Value * @throws if sJWS is not comma separated string such like "Header.Payload.Signature". */ KJUR.jws.JWS.getEncodedSignatureValueFromJWS = function(sJWS) { if (sJWS.match(/^[^.]+\.[^.]+\.([^.]+)$/) == null) { throw "JWS signature is not a form of 'Head.Payload.SigValue'."; } return RegExp.$1; }; /** * IntDate class for time representation for JSON Web Token(JWT) * @class KJUR.jws.IntDate class * @name KJUR.jws.IntDate * @since jws 3.0.1 * @description * Utility class for IntDate which is integer representation of UNIX origin time * used in JSON Web Token(JWT). */ KJUR.jws.IntDate = function() { }; /** * @name get * @memberOf KJUR.jws.IntDate * @function * @static * @param {String} s string of time representation * @return {Integer} UNIX origin time in seconds for argument 's' * @since jws 3.0.1 * @throws "unsupported format: s" when malformed format * @description * This method will accept following representation of time. * */ KJUR.jws.IntDate.get = function(s) { if (s == "now") { return KJUR.jws.IntDate.getNow(); } else if (s == "now + 1hour") { return KJUR.jws.IntDate.getNow() + 60 * 60; } else if (s == "now + 1day") { return KJUR.jws.IntDate.getNow() + 60 * 60 * 24; } else if (s == "now + 1month") { return KJUR.jws.IntDate.getNow() + 60 * 60 * 24 * 30; } else if (s == "now + 1year") { return KJUR.jws.IntDate.getNow() + 60 * 60 * 24 * 365; } else if (s.match(/Z$/)) { return KJUR.jws.IntDate.getZulu(s); } else if (s.match(/^[0-9]+$/)) { return parseInt(s); } throw "unsupported format: " + s; }; KJUR.jws.IntDate.getZulu = function(s) { if (a = s.match(/(\d{4})(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)Z/)) { var year = parseInt(RegExp.$1); var month = parseInt(RegExp.$2) - 1; var day = parseInt(RegExp.$3); var hour = parseInt(RegExp.$4); var min = parseInt(RegExp.$5); var sec = parseInt(RegExp.$6); var d = new Date(Date.UTC(year, month, day, hour, min, sec)); return ~~(d / 1000); } throw "unsupported format: " + s; }; /* * @since jws 3.0.1 */ KJUR.jws.IntDate.getNow = function() { var d = ~~(new Date() / 1000); return d; }; /* * @since jws 3.0.1 */ KJUR.jws.IntDate.intDate2UTCString = function(intDate) { var d = new Date(intDate * 1000); return d.toUTCString(); }; /* * @since jws 3.0.1 */ KJUR.jws.IntDate.intDate2Zulu = function(intDate) { var d = new Date(intDate * 1000); var year = ("0000" + d.getUTCFullYear()).slice(-4); var mon = ("00" + (d.getUTCMonth() + 1)).slice(-2); var day = ("00" + d.getUTCDate()).slice(-2); var hour = ("00" + d.getUTCHours()).slice(-2); var min = ("00" + d.getUTCMinutes()).slice(-2); var sec = ("00" + d.getUTCSeconds()).slice(-2); return year + mon + day + hour + min + sec + "Z"; };