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