/*! 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 value | spec requirement | jsjws support |
* HS256 | REQUIRED | SUPPORTED |
* HS384 | OPTIONAL | SUPPORTED |
* HS512 | OPTIONAL | SUPPORTED |
* RS256 | RECOMMENDED | SUPPORTED |
* RS384 | OPTIONAL | SUPPORTED |
* RS512 | OPTIONAL | SUPPORTED |
* ES256 | RECOMMENDED+ | SUPPORTED |
* ES384 | OPTIONAL | SUPPORTED |
* ES512 | OPTIONAL | - |
* PS256 | OPTIONAL | SUPPORTED |
* PS384 | OPTIONAL | SUPPORTED |
* PS512 | OPTIONAL | SUPPORTED |
* none | REQUIRED | SUPPORTED(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 value | spec requirement | jsjws support |
* HS256 | REQUIRED | SUPPORTED |
* HS384 | OPTIONAL | - |
* HS512 | OPTIONAL | SUPPORTED |
* RS256 | RECOMMENDED | SUPPORTED |
* RS384 | OPTIONAL | SUPPORTED |
* RS512 | OPTIONAL | SUPPORTED |
* ES256 | RECOMMENDED+ | SUPPORTED |
* ES384 | OPTIONAL | SUPPORTED |
* ES512 | OPTIONAL | - |
* PS256 | OPTIONAL | SUPPORTED |
* PS384 | OPTIONAL | SUPPORTED |
* PS512 | OPTIONAL | SUPPORTED |
* none | REQUIRED | SUPPORTED(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.
*
* - In case 'alg' is 'HS*' in the JWS header,
* 'key' shall be hexadecimal string for Hmac{256,384,512} shared secret key.
* Otherwise it raise an error.
* - In case 'alg' is 'RS*' or 'PS*' in the JWS header,
* 'key' shall be a RSAKey object or a PEM string of
* X.509 RSA public key certificate or PKCS#8 RSA public key.
* Otherwise it raise an error.
* - In case 'alg' is 'ES*' in the JWS header,
* 'key' shall be a KJUR.crypto.ECDSA object or a PEM string of
* X.509 ECC public key certificate or PKCS#8 ECC public key.
* Otherwise it raise an error.
* - In case 'alg' is 'none' in the JWS header,
* validation not supported after jsjws 3.1.0.
*
*
*
* 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.
*
* - now - current time
* - now + 1hour - after 1 hour from now
* - now + 1day - after 1 day from now
* - now + 1month - after 30 days from now
* - now + 1year - after 365 days from now
* - YYYYmmDDHHMMSSZ - UTC time (ex. 20130828235959Z)
* - number - UNIX origin time (seconds from 1970-01-01 00:00:00) (ex. 1377714748)
*
*/
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";
};