1 /*! rsasign-1.2.js (c) 2012 Kenji Urushima | kjur.github.com/jsrsasign/license 2 */ 3 // 4 // rsa-sign.js - adding signing functions to RSAKey class. 5 // 6 // 7 // version: 1.2.1 (08 May 2012) 8 // 9 // Copyright (c) 2010-2012 Kenji Urushima (kenji.urushima@gmail.com) 10 // 11 // This software is licensed under the terms of the MIT License. 12 // http://kjur.github.com/jsrsasign/license/ 13 // 14 // The above copyright and license notice shall be 15 // included in all copies or substantial portions of the Software. 16 17 // 18 // Depends on: 19 // function sha1.hex(s) of sha1.js 20 // jsbn.js 21 // jsbn2.js 22 // rsa.js 23 // rsa2.js 24 // 25 26 // keysize / pmstrlen 27 // 512 / 128 28 // 1024 / 256 29 // 2048 / 512 30 // 4096 / 1024 31 32 /** 33 * @property {Dictionary} _RSASIGN_DIHEAD 34 * @description Array of head part of hexadecimal DigestInfo value for hash algorithms. 35 * You can add any DigestInfo hash algorith for signing. 36 * See PKCS#1 v2.1 spec (p38). 37 */ 38 var _RSASIGN_DIHEAD = []; 39 _RSASIGN_DIHEAD['sha1'] = "3021300906052b0e03021a05000414"; 40 _RSASIGN_DIHEAD['sha256'] = "3031300d060960864801650304020105000420"; 41 _RSASIGN_DIHEAD['sha384'] = "3041300d060960864801650304020205000430"; 42 _RSASIGN_DIHEAD['sha512'] = "3051300d060960864801650304020305000440"; 43 _RSASIGN_DIHEAD['md2'] = "3020300c06082a864886f70d020205000410"; 44 _RSASIGN_DIHEAD['md5'] = "3020300c06082a864886f70d020505000410"; 45 _RSASIGN_DIHEAD['ripemd160'] = "3021300906052b2403020105000414"; 46 47 /** 48 * @property {Dictionary} _RSASIGN_HASHHEXFUNC 49 * @description Array of functions which calculate hash and returns it as hexadecimal. 50 * You can add any hash algorithm implementations. 51 */ 52 var _RSASIGN_HASHHEXFUNC = []; 53 _RSASIGN_HASHHEXFUNC['sha1'] = function(s){return hex_sha1(s);}; // http://pajhome.org.uk/crypt/md5/md5.html 54 _RSASIGN_HASHHEXFUNC['sha256'] = function(s){return hex_sha256(s);} // http://pajhome.org.uk/crypt/md5/md5.html 55 _RSASIGN_HASHHEXFUNC['sha512'] = function(s){return hex_sha512(s);} // http://pajhome.org.uk/crypt/md5/md5.html 56 _RSASIGN_HASHHEXFUNC['md5'] = function(s){return hex_md5(s);}; // http://pajhome.org.uk/crypt/md5/md5.html 57 _RSASIGN_HASHHEXFUNC['ripemd160'] = function(s){return hex_rmd160(s);}; // http://pajhome.org.uk/crypt/md5/md5.html 58 59 //_RSASIGN_HASHHEXFUNC['sha1'] = function(s){return sha1.hex(s);} // http://user1.matsumoto.ne.jp/~goma/js/hash.html 60 //_RSASIGN_HASHHEXFUNC['sha256'] = function(s){return sha256.hex;} // http://user1.matsumoto.ne.jp/~goma/js/hash.html 61 62 var _RE_HEXDECONLY = new RegExp(""); 63 _RE_HEXDECONLY.compile("[^0-9a-f]", "gi"); 64 65 // ======================================================================== 66 // Signature Generation 67 // ======================================================================== 68 69 function _rsasign_getHexPaddedDigestInfoForString(s, keySize, hashAlg) { 70 var pmStrLen = keySize / 4; 71 var hashFunc = _RSASIGN_HASHHEXFUNC[hashAlg]; 72 var sHashHex = hashFunc(s); 73 74 var sHead = "0001"; 75 var sTail = "00" + _RSASIGN_DIHEAD[hashAlg] + sHashHex; 76 var sMid = ""; 77 var fLen = pmStrLen - sHead.length - sTail.length; 78 for (var i = 0; i < fLen; i += 2) { 79 sMid += "ff"; 80 } 81 sPaddedMessageHex = sHead + sMid + sTail; 82 return sPaddedMessageHex; 83 } 84 85 function _zeroPaddingOfSignature(hex, bitLength) { 86 var s = ""; 87 var nZero = bitLength / 4 - hex.length; 88 for (var i = 0; i < nZero; i++) { 89 s = s + "0"; 90 } 91 return s + hex; 92 } 93 94 /** 95 * sign for a message string with RSA private key.<br/> 96 * @name signString 97 * @memberOf RSAKey# 98 * @function 99 * @param {String} s message string to be signed. 100 * @param {String} hashAlg hash algorithm name for signing.<br/> 101 * @return returns hexadecimal string of signature value. 102 */ 103 function _rsasign_signString(s, hashAlg) { 104 //alert("this.n.bitLength() = " + this.n.bitLength()); 105 var hPM = _rsasign_getHexPaddedDigestInfoForString(s, this.n.bitLength(), hashAlg); 106 var biPaddedMessage = parseBigInt(hPM, 16); 107 var biSign = this.doPrivate(biPaddedMessage); 108 var hexSign = biSign.toString(16); 109 return _zeroPaddingOfSignature(hexSign, this.n.bitLength()); 110 } 111 112 function _rsasign_signStringWithSHA1(s) { 113 return _rsasign_signString(s, 'sha1'); 114 } 115 116 function _rsasign_signStringWithSHA256(s) { 117 return _rsasign_signString(s, 'sha256'); 118 } 119 120 // ======================================================================== 121 // Signature Verification 122 // ======================================================================== 123 124 function _rsasign_getDecryptSignatureBI(biSig, hN, hE) { 125 var rsa = new RSAKey(); 126 rsa.setPublic(hN, hE); 127 var biDecryptedSig = rsa.doPublic(biSig); 128 return biDecryptedSig; 129 } 130 131 function _rsasign_getHexDigestInfoFromSig(biSig, hN, hE) { 132 var biDecryptedSig = _rsasign_getDecryptSignatureBI(biSig, hN, hE); 133 var hDigestInfo = biDecryptedSig.toString(16).replace(/^1f+00/, ''); 134 return hDigestInfo; 135 } 136 137 function _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo) { 138 for (var algName in _RSASIGN_DIHEAD) { 139 var head = _RSASIGN_DIHEAD[algName]; 140 var len = head.length; 141 if (hDigestInfo.substring(0, len) == head) { 142 var a = [algName, hDigestInfo.substring(len)]; 143 return a; 144 } 145 } 146 return []; 147 } 148 149 function _rsasign_verifySignatureWithArgs(sMsg, biSig, hN, hE) { 150 var hDigestInfo = _rsasign_getHexDigestInfoFromSig(biSig, hN, hE); 151 var digestInfoAry = _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo); 152 if (digestInfoAry.length == 0) return false; 153 var algName = digestInfoAry[0]; 154 var diHashValue = digestInfoAry[1]; 155 var ff = _RSASIGN_HASHHEXFUNC[algName]; 156 var msgHashValue = ff(sMsg); 157 return (diHashValue == msgHashValue); 158 } 159 160 function _rsasign_verifyHexSignatureForMessage(hSig, sMsg) { 161 var biSig = parseBigInt(hSig, 16); 162 var result = _rsasign_verifySignatureWithArgs(sMsg, biSig, 163 this.n.toString(16), 164 this.e.toString(16)); 165 return result; 166 } 167 168 /** 169 * verifies a sigature for a message string with RSA public key.<br/> 170 * @name verifyString 171 * @memberOf RSAKey# 172 * @function 173 * @param {String} sMsg message string to be verified. 174 * @param {String} hSig hexadecimal string of siganture.<br/> 175 * non-hexadecimal charactors including new lines will be ignored. 176 * @return returns 1 if valid, otherwise 0 177 */ 178 function _rsasign_verifyString(sMsg, hSig) { 179 hSig = hSig.replace(_RE_HEXDECONLY, ''); 180 if (hSig.length != this.n.bitLength() / 4) return 0; 181 hSig = hSig.replace(/[ \n]+/g, ""); 182 var biSig = parseBigInt(hSig, 16); 183 var biDecryptedSig = this.doPublic(biSig); 184 var hDigestInfo = biDecryptedSig.toString(16).replace(/^1f+00/, ''); 185 var digestInfoAry = _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo); 186 187 if (digestInfoAry.length == 0) return false; 188 var algName = digestInfoAry[0]; 189 var diHashValue = digestInfoAry[1]; 190 var ff = _RSASIGN_HASHHEXFUNC[algName]; 191 var msgHashValue = ff(sMsg); 192 return (diHashValue == msgHashValue); 193 } 194 195 RSAKey.prototype.signString = _rsasign_signString; 196 RSAKey.prototype.signStringWithSHA1 = _rsasign_signStringWithSHA1; 197 RSAKey.prototype.signStringWithSHA256 = _rsasign_signStringWithSHA256; 198 RSAKey.prototype.sign = _rsasign_signString; 199 RSAKey.prototype.signWithSHA1 = _rsasign_signStringWithSHA1; 200 RSAKey.prototype.signWithSHA256 = _rsasign_signStringWithSHA256; 201 202 RSAKey.prototype.verifyString = _rsasign_verifyString; 203 RSAKey.prototype.verifyHexSignatureForMessage = _rsasign_verifyHexSignatureForMessage; 204 RSAKey.prototype.verify = _rsasign_verifyString; 205 RSAKey.prototype.verifyHexSignatureForByteArrayMessage = _rsasign_verifyHexSignatureForMessage; 206 207 /** 208 * @name RSAKey 209 * @class 210 * @description Tom Wu's RSA Key class and extension 211 */ 212