1 /*! rsasign-1.2.7.js (c) 2012 Kenji Urushima | kjur.github.com/jsrsasign/license
  2  */
  3 /*
  4  * rsa-sign.js - adding signing functions to RSAKey class.
  5  *
  6  * version: 1.2.7 (2013 Aug 25)
  7  *
  8  * Copyright (c) 2010-2013 Kenji Urushima (kenji.urushima@gmail.com)
  9  *
 10  * This software is licensed under the terms of the MIT License.
 11  * http://kjur.github.com/jsrsasign/license/
 12  *
 13  * The above copyright and license notice shall be 
 14  * included in all copies or substantial portions of the Software.
 15  */
 16 
 17 /**
 18  * @fileOverview
 19  * @name rsasign-1.2.js
 20  * @author Kenji Urushima kenji.urushima@gmail.com
 21  * @version rsasign 1.2.7
 22  * @license <a href="http://kjur.github.io/jsrsasign/license/">MIT License</a>
 23  */
 24 
 25 var _RE_HEXDECONLY = new RegExp("");
 26 _RE_HEXDECONLY.compile("[^0-9a-f]", "gi");
 27 
 28 // ========================================================================
 29 // Signature Generation
 30 // ========================================================================
 31 
 32 function _rsasign_getHexPaddedDigestInfoForString(s, keySize, hashAlg) {
 33     var hashFunc = function(s) { return KJUR.crypto.Util.hashString(s, hashAlg); };
 34     var sHashHex = hashFunc(s);
 35 
 36     return KJUR.crypto.Util.getPaddedDigestInfoHex(sHashHex, hashAlg, keySize);
 37 }
 38 
 39 function _zeroPaddingOfSignature(hex, bitLength) {
 40     var s = "";
 41     var nZero = bitLength / 4 - hex.length;
 42     for (var i = 0; i < nZero; i++) {
 43 	s = s + "0";
 44     }
 45     return s + hex;
 46 }
 47 
 48 /**
 49  * sign for a message string with RSA private key.<br/>
 50  * @name signString
 51  * @memberOf RSAKey
 52  * @function
 53  * @param {String} s message string to be signed.
 54  * @param {String} hashAlg hash algorithm name for signing.<br/>
 55  * @return returns hexadecimal string of signature value.
 56  */
 57 function _rsasign_signString(s, hashAlg) {
 58     var hashFunc = function(s) { return KJUR.crypto.Util.hashString(s, hashAlg); };
 59     var sHashHex = hashFunc(s);
 60 
 61     return this.signWithMessageHash(sHashHex, hashAlg);
 62 }
 63 
 64 /**
 65  * sign hash value of message to be signed with RSA private key.<br/>
 66  * @name signWithMessageHash
 67  * @memberOf RSAKey
 68  * @function
 69  * @param {String} sHashHex hexadecimal string of hash value of message to be signed.
 70  * @param {String} hashAlg hash algorithm name for signing.<br/>
 71  * @return returns hexadecimal string of signature value.
 72  * @since rsasign 1.2.6
 73  */
 74 function _rsasign_signWithMessageHash(sHashHex, hashAlg) {
 75     var hPM = KJUR.crypto.Util.getPaddedDigestInfoHex(sHashHex, hashAlg, this.n.bitLength());
 76     var biPaddedMessage = parseBigInt(hPM, 16);
 77     var biSign = this.doPrivate(biPaddedMessage);
 78     var hexSign = biSign.toString(16);
 79     return _zeroPaddingOfSignature(hexSign, this.n.bitLength());
 80 }
 81 
 82 function _rsasign_signStringWithSHA1(s) {
 83     return _rsasign_signString.call(this, s, 'sha1');
 84 }
 85 
 86 function _rsasign_signStringWithSHA256(s) {
 87     return _rsasign_signString.call(this, s, 'sha256');
 88 }
 89 
 90 // PKCS#1 (PSS) mask generation function
 91 function pss_mgf1_str(seed, len, hash) {
 92     var mask = '', i = 0;
 93 
 94     while (mask.length < len) {
 95         mask += hextorstr(hash(rstrtohex(seed + String.fromCharCode.apply(String, [
 96                 (i & 0xff000000) >> 24,
 97                 (i & 0x00ff0000) >> 16,
 98                 (i & 0x0000ff00) >> 8,
 99                 i & 0x000000ff]))));
100         i += 1;
101     }
102 
103     return mask;
104 }
105 
106 /**
107  * sign for a message string with RSA private key by PKCS#1 PSS signing.<br/>
108  * @name signStringPSS
109  * @memberOf RSAKey
110  * @function
111  * @param {String} s message string to be signed.
112  * @param {String} hashAlg hash algorithm name for signing.
113  * @param {Integer} sLen salt byte length from 0 to (keybytelen - hashbytelen - 2).
114  *        There are two special values:
115  *        <ul>
116  *        <li>-1: sets the salt length to the digest length</li>
117  *        <li>-2: sets the salt length to maximum permissible value
118  *           (i.e. keybytelen - hashbytelen - 2)</li>
119  *        </ul>
120  *        DEFAULT is -1. (NOTE: OpenSSL's default is -2.)
121  * @return returns hexadecimal string of signature value.
122  */
123 function _rsasign_signStringPSS(s, hashAlg, sLen) {
124     var hashFunc = function(sHex) { return KJUR.crypto.Util.hashHex(sHex, hashAlg); } 
125     var hHash = hashFunc(rstrtohex(s));
126 
127     if (sLen === undefined) sLen = -1;
128     return this.signWithMessageHashPSS(hHash, hashAlg, sLen);
129 }
130 
131 /**
132  * sign hash value of message with RSA private key by PKCS#1 PSS signing.<br/>
133  * @name signWithMessageHashPSS
134  * @memberOf RSAKey
135  * @function
136  * @param {String} hHash hexadecimal hash value of message to be signed.
137  * @param {String} hashAlg hash algorithm name for signing.
138  * @param {Integer} sLen salt byte length from 0 to (keybytelen - hashbytelen - 2).
139  *        There are two special values:
140  *        <ul>
141  *        <li>-1: sets the salt length to the digest length</li>
142  *        <li>-2: sets the salt length to maximum permissible value
143  *           (i.e. keybytelen - hashbytelen - 2)</li>
144  *        </ul>
145  *        DEFAULT is -1. (NOTE: OpenSSL's default is -2.)
146  * @return returns hexadecimal string of signature value.
147  * @since rsasign 1.2.6
148  */
149 function _rsasign_signWithMessageHashPSS(hHash, hashAlg, sLen) {
150     var mHash = hextorstr(hHash);
151     var hLen = mHash.length;
152     var emBits = this.n.bitLength() - 1;
153     var emLen = Math.ceil(emBits / 8);
154     var i;
155     var hashFunc = function(sHex) { return KJUR.crypto.Util.hashHex(sHex, hashAlg); } 
156 
157     if (sLen === -1 || sLen === undefined) {
158         sLen = hLen; // same as hash length
159     } else if (sLen === -2) {
160         sLen = emLen - hLen - 2; // maximum
161     } else if (sLen < -2) {
162         throw "invalid salt length";
163     }
164 
165     if (emLen < (hLen + sLen + 2)) {
166         throw "data too long";
167     }
168 
169     var salt = '';
170 
171     if (sLen > 0) {
172         salt = new Array(sLen);
173         new SecureRandom().nextBytes(salt);
174         salt = String.fromCharCode.apply(String, salt);
175     }
176 
177     var H = hextorstr(hashFunc(rstrtohex('\x00\x00\x00\x00\x00\x00\x00\x00' + mHash + salt)));
178     var PS = [];
179 
180     for (i = 0; i < emLen - sLen - hLen - 2; i += 1) {
181         PS[i] = 0x00;
182     }
183 
184     var DB = String.fromCharCode.apply(String, PS) + '\x01' + salt;
185     var dbMask = pss_mgf1_str(H, DB.length, hashFunc);
186     var maskedDB = [];
187 
188     for (i = 0; i < DB.length; i += 1) {
189         maskedDB[i] = DB.charCodeAt(i) ^ dbMask.charCodeAt(i);
190     }
191 
192     var mask = (0xff00 >> (8 * emLen - emBits)) & 0xff;
193     maskedDB[0] &= ~mask;
194 
195     for (i = 0; i < hLen; i++) {
196         maskedDB.push(H.charCodeAt(i));
197     }
198 
199     maskedDB.push(0xbc);
200 
201     return _zeroPaddingOfSignature(this.doPrivate(new BigInteger(maskedDB)).toString(16),
202 				   this.n.bitLength());
203 }
204 
205 // ========================================================================
206 // Signature Verification
207 // ========================================================================
208 
209 function _rsasign_getDecryptSignatureBI(biSig, hN, hE) {
210     var rsa = new RSAKey();
211     rsa.setPublic(hN, hE);
212     var biDecryptedSig = rsa.doPublic(biSig);
213     return biDecryptedSig;
214 }
215 
216 function _rsasign_getHexDigestInfoFromSig(biSig, hN, hE) {
217     var biDecryptedSig = _rsasign_getDecryptSignatureBI(biSig, hN, hE);
218     var hDigestInfo = biDecryptedSig.toString(16).replace(/^1f+00/, '');
219     return hDigestInfo;
220 }
221 
222 function _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo) {
223     for (var algName in KJUR.crypto.Util.DIGESTINFOHEAD) {
224 	var head = KJUR.crypto.Util.DIGESTINFOHEAD[algName];
225 	var len = head.length;
226 	if (hDigestInfo.substring(0, len) == head) {
227 	    var a = [algName, hDigestInfo.substring(len)];
228 	    return a;
229 	}
230     }
231     return [];
232 }
233 
234 function _rsasign_verifySignatureWithArgs(sMsg, biSig, hN, hE) {
235     var hDigestInfo = _rsasign_getHexDigestInfoFromSig(biSig, hN, hE);
236     var digestInfoAry = _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo);
237     if (digestInfoAry.length == 0) return false;
238     var algName = digestInfoAry[0];
239     var diHashValue = digestInfoAry[1];
240     var ff = function(s) { return KJUR.crypto.Util.hashString(s, algName); };
241     var msgHashValue = ff(sMsg);
242     return (diHashValue == msgHashValue);
243 }
244 
245 function _rsasign_verifyHexSignatureForMessage(hSig, sMsg) {
246     var biSig = parseBigInt(hSig, 16);
247     var result = _rsasign_verifySignatureWithArgs(sMsg, biSig,
248 						  this.n.toString(16),
249 						  this.e.toString(16));
250     return result;
251 }
252 
253 /**
254  * verifies a sigature for a message string with RSA public key.<br/>
255  * @name verifyString
256  * @memberOf RSAKey#
257  * @function
258  * @param {String} sMsg message string to be verified.
259  * @param {String} hSig hexadecimal string of siganture.<br/>
260  *                 non-hexadecimal charactors including new lines will be ignored.
261  * @return returns 1 if valid, otherwise 0
262  */
263 function _rsasign_verifyString(sMsg, hSig) {
264     hSig = hSig.replace(_RE_HEXDECONLY, '');
265     hSig = hSig.replace(/[ \n]+/g, "");
266     var biSig = parseBigInt(hSig, 16);
267     if (biSig.bitLength() > this.n.bitLength()) return 0;
268     var biDecryptedSig = this.doPublic(biSig);
269     var hDigestInfo = biDecryptedSig.toString(16).replace(/^1f+00/, '');
270     var digestInfoAry = _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo);
271   
272     if (digestInfoAry.length == 0) return false;
273     var algName = digestInfoAry[0];
274     var diHashValue = digestInfoAry[1];
275     var ff = function(s) { return KJUR.crypto.Util.hashString(s, algName); };
276     var msgHashValue = ff(sMsg);
277     return (diHashValue == msgHashValue);
278 }
279 
280 /**
281  * verifies a sigature for a message string with RSA public key.<br/>
282  * @name verifyWithMessageHash
283  * @memberOf RSAKey
284  * @function
285  * @param {String} sHashHex hexadecimal hash value of message to be verified.
286  * @param {String} hSig hexadecimal string of siganture.<br/>
287  *                 non-hexadecimal charactors including new lines will be ignored.
288  * @return returns 1 if valid, otherwise 0
289  * @since rsasign 1.2.6
290  */
291 function _rsasign_verifyWithMessageHash(sHashHex, hSig) {
292     hSig = hSig.replace(_RE_HEXDECONLY, '');
293     hSig = hSig.replace(/[ \n]+/g, "");
294     var biSig = parseBigInt(hSig, 16);
295     if (biSig.bitLength() > this.n.bitLength()) return 0;
296     var biDecryptedSig = this.doPublic(biSig);
297     var hDigestInfo = biDecryptedSig.toString(16).replace(/^1f+00/, '');
298     var digestInfoAry = _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo);
299   
300     if (digestInfoAry.length == 0) return false;
301     var algName = digestInfoAry[0];
302     var diHashValue = digestInfoAry[1];
303     return (diHashValue == sHashHex);
304 }
305 
306 /**
307  * verifies a sigature for a message string with RSA public key by PKCS#1 PSS sign.<br/>
308  * @name verifyStringPSS
309  * @memberOf RSAKey
310  * @function
311  * @param {String} sMsg message string to be verified.
312  * @param {String} hSig hexadecimal string of signature value
313  * @param {String} hashAlg hash algorithm name
314  * @param {Integer} sLen salt byte length from 0 to (keybytelen - hashbytelen - 2).
315  *        There are two special values:
316  *        <ul>
317  *        <li>-1: sets the salt length to the digest length</li>
318  *        <li>-2: sets the salt length to maximum permissible value
319  *           (i.e. keybytelen - hashbytelen - 2)</li>
320  *        </ul>
321  *        DEFAULT is -1. (NOTE: OpenSSL's default is -2.)
322  * @return returns true if valid, otherwise false
323  */
324 function _rsasign_verifyStringPSS(sMsg, hSig, hashAlg, sLen) {
325     var hashFunc = function(sHex) { return KJUR.crypto.Util.hashHex(sHex, hashAlg); };
326     var hHash = hashFunc(rstrtohex(sMsg));
327 
328     if (sLen === undefined) sLen = -1;
329     return this.verifyWithMessageHashPSS(hHash, hSig, hashAlg, sLen);
330 }
331 
332 /**
333  * verifies a sigature for a hash value of message string with RSA public key by PKCS#1 PSS sign.<br/>
334  * @name verifyWithMessageHashPSS
335  * @memberOf RSAKey
336  * @function
337  * @param {String} hHash hexadecimal hash value of message string to be verified.
338  * @param {String} hSig hexadecimal string of signature value
339  * @param {String} hashAlg hash algorithm name
340  * @param {Integer} sLen salt byte length from 0 to (keybytelen - hashbytelen - 2).
341  *        There are two special values:
342  *        <ul>
343  *        <li>-1: sets the salt length to the digest length</li>
344  *        <li>-2: sets the salt length to maximum permissible value
345  *           (i.e. keybytelen - hashbytelen - 2)</li>
346  *        </ul>
347  *        DEFAULT is -1 (NOTE: OpenSSL's default is -2.)
348  * @return returns true if valid, otherwise false
349  * @since rsasign 1.2.6
350  */
351 function _rsasign_verifyWithMessageHashPSS(hHash, hSig, hashAlg, sLen) {
352     var biSig = new BigInteger(hSig, 16);
353 
354     if (biSig.bitLength() > this.n.bitLength()) {
355         return false;
356     }
357 
358     var hashFunc = function(sHex) { return KJUR.crypto.Util.hashHex(sHex, hashAlg); };
359     var mHash = hextorstr(hHash);
360     var hLen = mHash.length;
361     var emBits = this.n.bitLength() - 1;
362     var emLen = Math.ceil(emBits / 8);
363     var i;
364 
365     if (sLen === -1 || sLen === undefined) {
366         sLen = hLen; // same as hash length
367     } else if (sLen === -2) {
368         sLen = emLen - hLen - 2; // recover
369     } else if (sLen < -2) {
370         throw "invalid salt length";
371     }
372 
373     if (emLen < (hLen + sLen + 2)) {
374         throw "data too long";
375     }
376 
377     var em = this.doPublic(biSig).toByteArray();
378 
379     for (i = 0; i < em.length; i += 1) {
380         em[i] &= 0xff;
381     }
382 
383     while (em.length < emLen) {
384         em.unshift(0);
385     }
386 
387     if (em[emLen -1] !== 0xbc) {
388         throw "encoded message does not end in 0xbc";
389     }
390 
391     em = String.fromCharCode.apply(String, em);
392 
393     var maskedDB = em.substr(0, emLen - hLen - 1);
394     var H = em.substr(maskedDB.length, hLen);
395 
396     var mask = (0xff00 >> (8 * emLen - emBits)) & 0xff;
397 
398     if ((maskedDB.charCodeAt(0) & mask) !== 0) {
399         throw "bits beyond keysize not zero";
400     }
401 
402     var dbMask = pss_mgf1_str(H, maskedDB.length, hashFunc);
403     var DB = [];
404 
405     for (i = 0; i < maskedDB.length; i += 1) {
406         DB[i] = maskedDB.charCodeAt(i) ^ dbMask.charCodeAt(i);
407     }
408 
409     DB[0] &= ~mask;
410 
411     var checkLen = emLen - hLen - sLen - 2;
412 
413     for (i = 0; i < checkLen; i += 1) {
414         if (DB[i] !== 0x00) {
415             throw "leftmost octets not zero";
416         }
417     }
418 
419     if (DB[checkLen] !== 0x01) {
420         throw "0x01 marker not found";
421     }
422 
423     return H === hextorstr(hashFunc(rstrtohex('\x00\x00\x00\x00\x00\x00\x00\x00' + mHash +
424 				     String.fromCharCode.apply(String, DB.slice(-sLen)))));
425 }
426 
427 RSAKey.prototype.signWithMessageHash = _rsasign_signWithMessageHash;
428 RSAKey.prototype.signString = _rsasign_signString;
429 RSAKey.prototype.signStringWithSHA1 = _rsasign_signStringWithSHA1;
430 RSAKey.prototype.signStringWithSHA256 = _rsasign_signStringWithSHA256;
431 RSAKey.prototype.sign = _rsasign_signString;
432 RSAKey.prototype.signWithSHA1 = _rsasign_signStringWithSHA1;
433 RSAKey.prototype.signWithSHA256 = _rsasign_signStringWithSHA256;
434 
435 RSAKey.prototype.signWithMessageHashPSS = _rsasign_signWithMessageHashPSS;
436 RSAKey.prototype.signStringPSS = _rsasign_signStringPSS;
437 RSAKey.prototype.signPSS = _rsasign_signStringPSS;
438 RSAKey.SALT_LEN_HLEN = -1;
439 RSAKey.SALT_LEN_MAX = -2;
440 
441 RSAKey.prototype.verifyWithMessageHash = _rsasign_verifyWithMessageHash;
442 RSAKey.prototype.verifyString = _rsasign_verifyString;
443 RSAKey.prototype.verifyHexSignatureForMessage = _rsasign_verifyHexSignatureForMessage;
444 RSAKey.prototype.verify = _rsasign_verifyString;
445 RSAKey.prototype.verifyHexSignatureForByteArrayMessage = _rsasign_verifyHexSignatureForMessage;
446 
447 RSAKey.prototype.verifyWithMessageHashPSS = _rsasign_verifyWithMessageHashPSS;
448 RSAKey.prototype.verifyStringPSS = _rsasign_verifyStringPSS;
449 RSAKey.prototype.verifyPSS = _rsasign_verifyStringPSS;
450 RSAKey.SALT_LEN_RECOVER = -2;
451 
452 /**
453  * @name RSAKey
454  * @class key of RSA public key algorithm
455  * @description Tom Wu's RSA Key class and extension
456  */
457