/*! rsasign-1.2.js (c) 2012 Kenji Urushima | kjur.github.com/jsrsasign/license */ // // rsa-sign.js - adding signing functions to RSAKey class. // // // version: 1.2.1 (08 May 2012) // // Copyright (c) 2010-2012 Kenji Urushima (kenji.urushima@gmail.com) // // This software is licensed under the terms of the MIT License. // http://kjur.github.com/jsrsasign/license/ // // The above copyright and license notice shall be // included in all copies or substantial portions of the Software. // // Depends on: // function sha1.hex(s) of sha1.js // jsbn.js // jsbn2.js // rsa.js // rsa2.js // // keysize / pmstrlen // 512 / 128 // 1024 / 256 // 2048 / 512 // 4096 / 1024 /** * @property {Dictionary} _RSASIGN_DIHEAD * @description Array of head part of hexadecimal DigestInfo value for hash algorithms. * You can add any DigestInfo hash algorith for signing. * See PKCS#1 v2.1 spec (p38). */ var _RSASIGN_DIHEAD = []; _RSASIGN_DIHEAD['sha1'] = "3021300906052b0e03021a05000414"; _RSASIGN_DIHEAD['sha256'] = "3031300d060960864801650304020105000420"; _RSASIGN_DIHEAD['sha384'] = "3041300d060960864801650304020205000430"; _RSASIGN_DIHEAD['sha512'] = "3051300d060960864801650304020305000440"; _RSASIGN_DIHEAD['md2'] = "3020300c06082a864886f70d020205000410"; _RSASIGN_DIHEAD['md5'] = "3020300c06082a864886f70d020505000410"; _RSASIGN_DIHEAD['ripemd160'] = "3021300906052b2403020105000414"; /** * @property {Dictionary} _RSASIGN_HASHHEXFUNC * @description Array of functions which calculate hash and returns it as hexadecimal. * You can add any hash algorithm implementations. */ var _RSASIGN_HASHHEXFUNC = []; _RSASIGN_HASHHEXFUNC['sha1'] = function(s){return hex_sha1(s);}; // http://pajhome.org.uk/crypt/md5/md5.html _RSASIGN_HASHHEXFUNC['sha256'] = function(s){return hex_sha256(s);} // http://pajhome.org.uk/crypt/md5/md5.html _RSASIGN_HASHHEXFUNC['sha512'] = function(s){return hex_sha512(s);} // http://pajhome.org.uk/crypt/md5/md5.html _RSASIGN_HASHHEXFUNC['md5'] = function(s){return hex_md5(s);}; // http://pajhome.org.uk/crypt/md5/md5.html _RSASIGN_HASHHEXFUNC['ripemd160'] = function(s){return hex_rmd160(s);}; // http://pajhome.org.uk/crypt/md5/md5.html //_RSASIGN_HASHHEXFUNC['sha1'] = function(s){return sha1.hex(s);} // http://user1.matsumoto.ne.jp/~goma/js/hash.html //_RSASIGN_HASHHEXFUNC['sha256'] = function(s){return sha256.hex;} // http://user1.matsumoto.ne.jp/~goma/js/hash.html var _RE_HEXDECONLY = new RegExp(""); _RE_HEXDECONLY.compile("[^0-9a-f]", "gi"); // ======================================================================== // Signature Generation // ======================================================================== function _rsasign_getHexPaddedDigestInfoForString(s, keySize, hashAlg) { var pmStrLen = keySize / 4; var hashFunc = _RSASIGN_HASHHEXFUNC[hashAlg]; var sHashHex = hashFunc(s); var sHead = "0001"; var sTail = "00" + _RSASIGN_DIHEAD[hashAlg] + sHashHex; var sMid = ""; var fLen = pmStrLen - sHead.length - sTail.length; for (var i = 0; i < fLen; i += 2) { sMid += "ff"; } sPaddedMessageHex = sHead + sMid + sTail; return sPaddedMessageHex; } function _zeroPaddingOfSignature(hex, bitLength) { var s = ""; var nZero = bitLength / 4 - hex.length; for (var i = 0; i < nZero; i++) { s = s + "0"; } return s + hex; } /** * sign for a message string with RSA private key.
* @name signString * @memberOf RSAKey# * @function * @param {String} s message string to be signed. * @param {String} hashAlg hash algorithm name for signing.
* @return returns hexadecimal string of signature value. */ function _rsasign_signString(s, hashAlg) { //alert("this.n.bitLength() = " + this.n.bitLength()); var hPM = _rsasign_getHexPaddedDigestInfoForString(s, this.n.bitLength(), hashAlg); var biPaddedMessage = parseBigInt(hPM, 16); var biSign = this.doPrivate(biPaddedMessage); var hexSign = biSign.toString(16); return _zeroPaddingOfSignature(hexSign, this.n.bitLength()); } function _rsasign_signStringWithSHA1(s) { return _rsasign_signString(s, 'sha1'); } function _rsasign_signStringWithSHA256(s) { return _rsasign_signString(s, 'sha256'); } // ======================================================================== // Signature Verification // ======================================================================== function _rsasign_getDecryptSignatureBI(biSig, hN, hE) { var rsa = new RSAKey(); rsa.setPublic(hN, hE); var biDecryptedSig = rsa.doPublic(biSig); return biDecryptedSig; } function _rsasign_getHexDigestInfoFromSig(biSig, hN, hE) { var biDecryptedSig = _rsasign_getDecryptSignatureBI(biSig, hN, hE); var hDigestInfo = biDecryptedSig.toString(16).replace(/^1f+00/, ''); return hDigestInfo; } function _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo) { for (var algName in _RSASIGN_DIHEAD) { var head = _RSASIGN_DIHEAD[algName]; var len = head.length; if (hDigestInfo.substring(0, len) == head) { var a = [algName, hDigestInfo.substring(len)]; return a; } } return []; } function _rsasign_verifySignatureWithArgs(sMsg, biSig, hN, hE) { var hDigestInfo = _rsasign_getHexDigestInfoFromSig(biSig, hN, hE); var digestInfoAry = _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo); if (digestInfoAry.length == 0) return false; var algName = digestInfoAry[0]; var diHashValue = digestInfoAry[1]; var ff = _RSASIGN_HASHHEXFUNC[algName]; var msgHashValue = ff(sMsg); return (diHashValue == msgHashValue); } function _rsasign_verifyHexSignatureForMessage(hSig, sMsg) { var biSig = parseBigInt(hSig, 16); var result = _rsasign_verifySignatureWithArgs(sMsg, biSig, this.n.toString(16), this.e.toString(16)); return result; } /** * verifies a sigature for a message string with RSA public key.
* @name verifyString * @memberOf RSAKey# * @function * @param {String} sMsg message string to be verified. * @param {String} hSig hexadecimal string of siganture.
* non-hexadecimal charactors including new lines will be ignored. * @return returns 1 if valid, otherwise 0 */ function _rsasign_verifyString(sMsg, hSig) { hSig = hSig.replace(_RE_HEXDECONLY, ''); if (hSig.length != this.n.bitLength() / 4) return 0; hSig = hSig.replace(/[ \n]+/g, ""); var biSig = parseBigInt(hSig, 16); var biDecryptedSig = this.doPublic(biSig); var hDigestInfo = biDecryptedSig.toString(16).replace(/^1f+00/, ''); var digestInfoAry = _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo); if (digestInfoAry.length == 0) return false; var algName = digestInfoAry[0]; var diHashValue = digestInfoAry[1]; var ff = _RSASIGN_HASHHEXFUNC[algName]; var msgHashValue = ff(sMsg); return (diHashValue == msgHashValue); } RSAKey.prototype.signString = _rsasign_signString; RSAKey.prototype.signStringWithSHA1 = _rsasign_signStringWithSHA1; RSAKey.prototype.signStringWithSHA256 = _rsasign_signStringWithSHA256; RSAKey.prototype.sign = _rsasign_signString; RSAKey.prototype.signWithSHA1 = _rsasign_signStringWithSHA1; RSAKey.prototype.signWithSHA256 = _rsasign_signStringWithSHA256; RSAKey.prototype.verifyString = _rsasign_verifyString; RSAKey.prototype.verifyHexSignatureForMessage = _rsasign_verifyHexSignatureForMessage; RSAKey.prototype.verify = _rsasign_verifyString; RSAKey.prototype.verifyHexSignatureForByteArrayMessage = _rsasign_verifyHexSignatureForMessage; /** * @name RSAKey * @class * @description Tom Wu's RSA Key class and extension */