blob: 0da28279951d53f473dc87161966d101e94c501d [file] [log] [blame]
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -07001/*! 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 */
38var _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 */
52var _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
Axel Colin de Verdiere49c08a72012-06-05 23:04:16 -070059//@author axelcdv
60var _RSASIGN_HASHBYTEFUNC = [];
61_RSASIGN_HASHBYTEFUNC['sha256'] = function(byteArray){return hex_sha256_from_bytes(byteArray);};
62
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070063//_RSASIGN_HASHHEXFUNC['sha1'] = function(s){return sha1.hex(s);} // http://user1.matsumoto.ne.jp/~goma/js/hash.html
64//_RSASIGN_HASHHEXFUNC['sha256'] = function(s){return sha256.hex;} // http://user1.matsumoto.ne.jp/~goma/js/hash.html
65
66var _RE_HEXDECONLY = new RegExp("");
67_RE_HEXDECONLY.compile("[^0-9a-f]", "gi");
68
69// ========================================================================
70// Signature Generation
71// ========================================================================
72
73function _rsasign_getHexPaddedDigestInfoForString(s, keySize, hashAlg) {
74 var pmStrLen = keySize / 4;
75 var hashFunc = _RSASIGN_HASHHEXFUNC[hashAlg];
76 var sHashHex = hashFunc(s);
77
78 var sHead = "0001";
79 var sTail = "00" + _RSASIGN_DIHEAD[hashAlg] + sHashHex;
80 var sMid = "";
81 var fLen = pmStrLen - sHead.length - sTail.length;
82 for (var i = 0; i < fLen; i += 2) {
83 sMid += "ff";
84 }
85 sPaddedMessageHex = sHead + sMid + sTail;
86 return sPaddedMessageHex;
87}
88
89
Jeff Thompson146d7de2012-11-17 16:15:28 -080090//@author: Meki Cheraoui
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070091function _rsasign_getHexPaddedDigestInfoForStringHEX(s, keySize, hashAlg) {
92 var pmStrLen = keySize / 4;
93 var hashFunc = _RSASIGN_HASHHEXFUNC[hashAlg];
94 var sHashHex = hashFunc(s);
95
96 var sHead = "0001";
97 var sTail = "00" + _RSASIGN_DIHEAD[hashAlg] + sHashHex;
98 var sMid = "";
99 var fLen = pmStrLen - sHead.length - sTail.length;
100 for (var i = 0; i < fLen; i += 2) {
101 sMid += "ff";
102 }
103 sPaddedMessageHex = sHead + sMid + sTail;
104 return sPaddedMessageHex;
105}
106
Axel Colin de Verdiere49c08a72012-06-05 23:04:16 -0700107/**
108 * Apply padding, then computes the hash of the given byte array, according to the key size and with the hash algorithm
109 * @param byteArray (byte[])
110 * @param keySize (int)
111 * @param hashAlg the hash algorithm to apply (string)
112 * @return the hash of byteArray
113 */
114function _rsasign_getHexPaddedDigestInfoForByteArray(byteArray, keySize, hashAlg){
115 var pmStrLen = keySize / 4;
116 var hashFunc = _RSASIGN_HASHBYTEFUNC[hashAlg];
117 var sHashHex = hashFunc(byteArray); //returns hex hash
118
119 var sHead = "0001";
120 var sTail = "00" + _RSASIGN_DIHEAD[hashAlg] + sHashHex;
121 var sMid = "";
122 var fLen = pmStrLen - sHead.length - sTail.length;
123 for (var i = 0; i < fLen; i += 2) {
124 sMid += "ff";
125 }
126 sPaddedMessageHex = sHead + sMid + sTail;
127 return sPaddedMessageHex;
128}
129
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -0700130function _zeroPaddingOfSignature(hex, bitLength) {
131 var s = "";
132 var nZero = bitLength / 4 - hex.length;
133 for (var i = 0; i < nZero; i++) {
134 s = s + "0";
135 }
136 return s + hex;
137}
138
139/**
140 * sign for a message string with RSA private key.<br/>
141 * @name signString
142 * @memberOf RSAKey#
143 * @function
144 * @param {String} s message string to be signed.
145 * @param {String} hashAlg hash algorithm name for signing.<br/>
146 * @return returns hexadecimal string of signature value.
147 */
148function _rsasign_signString(s, hashAlg) {
149 //alert("this.n.bitLength() = " + this.n.bitLength());
150 var hPM = _rsasign_getHexPaddedDigestInfoForString(s, this.n.bitLength(), hashAlg);
151 var biPaddedMessage = parseBigInt(hPM, 16);
152 var biSign = this.doPrivate(biPaddedMessage);
153 var hexSign = biSign.toString(16);
154 return _zeroPaddingOfSignature(hexSign, this.n.bitLength());
155}
156
157//@author: ucla-cs
158function _rsasign_signStringHEX(s, hashAlg) {
159 //alert("this.n.bitLength() = " + this.n.bitLength());
160 var hPM = _rsasign_getHexPaddedDigestInfoForString(s, this.n.bitLength(), hashAlg);
161 var biPaddedMessage = parseBigInt(hPM, 16);
162 var biSign = this.doPrivate(biPaddedMessage);
163 var hexSign = biSign.toString(16);
164 return _zeroPaddingOfSignature(hexSign, this.n.bitLength());
165}
166
167
Axel Colin de Verdiere49c08a72012-06-05 23:04:16 -0700168/**
169 * Sign a message byteArray with an RSA private key
170 * @name signByteArray
171 * @memberOf RSAKey#
172 * @function
173 * @param {byte[]} byteArray
174 * @param {Sring} hashAlg the hash algorithm to apply
175 * @param {RSAKey} rsa key to sign with: hack because the context is lost here
176 * @return hexadecimal string of signature value
177 */
178function _rsasign_signByteArray(byteArray, hashAlg, rsaKey) {
179 var hPM = _rsasign_getHexPaddedDigestInfoForByteArray(byteArray, rsaKey.n.bitLength(), hashAlg); ///hack because the context is lost here
180 var biPaddedMessage = parseBigInt(hPM, 16);
181 var biSign = rsaKey.doPrivate(biPaddedMessage); //hack because the context is lost here
182 var hexSign = biSign.toString(16);
183 return _zeroPaddingOfSignature(hexSign, rsaKey.n.bitLength()); //hack because the context is lost here
184}
185
186/**
187 * Sign a byte array with the Sha-256 algorithm
188 * @param {byte[]} byteArray
189 * @return hexadecimal string of signature value
190 */
191function _rsasign_signByteArrayWithSHA256(byteArray){
192 return _rsasign_signByteArray(byteArray, 'sha256', this); //Hack because the context is lost in the next function
193}
194
195
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -0700196function _rsasign_signStringWithSHA1(s) {
197 return _rsasign_signString(s, 'sha1');
198}
199
200function _rsasign_signStringWithSHA256(s) {
201 return _rsasign_signString(s, 'sha256');
202}
203
204// ========================================================================
205// Signature Verification
206// ========================================================================
207
208function _rsasign_getDecryptSignatureBI(biSig, hN, hE) {
209 var rsa = new RSAKey();
210 rsa.setPublic(hN, hE);
211 var biDecryptedSig = rsa.doPublic(biSig);
212 return biDecryptedSig;
213}
214
215function _rsasign_getHexDigestInfoFromSig(biSig, hN, hE) {
216 var biDecryptedSig = _rsasign_getDecryptSignatureBI(biSig, hN, hE);
217 var hDigestInfo = biDecryptedSig.toString(16).replace(/^1f+00/, '');
218 return hDigestInfo;
219}
220
221function _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo) {
222 for (var algName in _RSASIGN_DIHEAD) {
223 var head = _RSASIGN_DIHEAD[algName];
224 var len = head.length;
225 if (hDigestInfo.substring(0, len) == head) {
226 var a = [algName, hDigestInfo.substring(len)];
227 return a;
228 }
229 }
230 return [];
231}
232
233function _rsasign_verifySignatureWithArgs(sMsg, biSig, hN, hE) {
234 var hDigestInfo = _rsasign_getHexDigestInfoFromSig(biSig, hN, hE);
235 var digestInfoAry = _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo);
236 if (digestInfoAry.length == 0) return false;
237 var algName = digestInfoAry[0];
238 var diHashValue = digestInfoAry[1];
239 var ff = _RSASIGN_HASHHEXFUNC[algName];
240 var msgHashValue = ff(sMsg);
241 return (diHashValue == msgHashValue);
242}
243
244function _rsasign_verifyHexSignatureForMessage(hSig, sMsg) {
245 var biSig = parseBigInt(hSig, 16);
246 var result = _rsasign_verifySignatureWithArgs(sMsg, biSig,
247 this.n.toString(16),
248 this.e.toString(16));
249 return result;
250}
251
252/**
253 * verifies a sigature for a message string with RSA public key.<br/>
254 * @name verifyString
255 * @memberOf RSAKey#
256 * @function
257 * @param {String} sMsg message string to be verified.
258 * @param {String} hSig hexadecimal string of siganture.<br/>
259 * non-hexadecimal charactors including new lines will be ignored.
260 * @return returns 1 if valid, otherwise 0
261 */
262function _rsasign_verifyString(sMsg, hSig) {
263 hSig = hSig.replace(_RE_HEXDECONLY, '');
264
265 if(LOG>3)console.log('n is '+this.n);
266 if(LOG>3)console.log('e is '+this.e);
267
268 if (hSig.length != this.n.bitLength() / 4) return 0;
269 hSig = hSig.replace(/[ \n]+/g, "");
270 var biSig = parseBigInt(hSig, 16);
271 var biDecryptedSig = this.doPublic(biSig);
272 var hDigestInfo = biDecryptedSig.toString(16).replace(/^1f+00/, '');
273 var digestInfoAry = _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo);
274
275 if (digestInfoAry.length == 0) return false;
276 var algName = digestInfoAry[0];
277 var diHashValue = digestInfoAry[1];
278 var ff = _RSASIGN_HASHHEXFUNC[algName];
279 var msgHashValue = ff(sMsg);
280 return (diHashValue == msgHashValue);
281}
282
Axel Colin de Verdiere49c08a72012-06-05 23:04:16 -0700283/**
284 * verifies a sigature for a message byte array with RSA public key.<br/>
285 * @name verifyByteArray
286 * @memberOf RSAKey#
287 * @function
288 * @param {byte[]} byteArray message byte array to be verified.
289 * @param {String} hSig hexadecimal string of signature.<br/>
290 * non-hexadecimal charactors including new lines will be ignored.
291 * @return returns 1 if valid, otherwise 0
292 */
Wentao Shang882e34e2013-01-05 02:49:51 -0800293function _rsasign_verifyByteArray(byteArray, witness, hSig) {
Axel Colin de Verdiere49c08a72012-06-05 23:04:16 -0700294 hSig = hSig.replace(_RE_HEXDECONLY, '');
295
296 if(LOG>3)console.log('n is '+this.n);
297 if(LOG>3)console.log('e is '+this.e);
298
299 if (hSig.length != this.n.bitLength() / 4) return 0;
300 hSig = hSig.replace(/[ \n]+/g, "");
301 var biSig = parseBigInt(hSig, 16);
302 var biDecryptedSig = this.doPublic(biSig);
303 var hDigestInfo = biDecryptedSig.toString(16).replace(/^1f+00/, '');
304 var digestInfoAry = _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo);
305
306 if (digestInfoAry.length == 0) return false;
307 var algName = digestInfoAry[0];
308 var diHashValue = digestInfoAry[1];
Wentao Shang882e34e2013-01-05 02:49:51 -0800309 var msgHashValue = null;
310
311 if (witness == null) {
312 var ff = _RSASIGN_HASHBYTEFUNC[algName];
313 msgHashValue = ff(byteArray);
314 } else {
315 // Compute merkle hash
Jeff Thompson48ff28a2013-02-18 22:53:29 -0800316 var h = hex_sha256_from_bytes(byteArray);
317 var index = witness.path.index;
318 for (var i = witness.path.digestList.length - 1; i >= 0; i--) {
Wentao Shang882e34e2013-01-05 02:49:51 -0800319 var str = "";
320 if (index % 2 == 0) {
321 str = h + witness.path.digestList[i];
322 } else {
323 str = witness.path.digestList[i] + h;
324 }
325 h = hex_sha256_from_bytes(DataUtils.toNumbers(str));
326 index = Math.floor(index / 2);
327 }
328 msgHashValue = hex_sha256_from_bytes(DataUtils.toNumbers(h));
329 }
330 //console.log(diHashValue);
331 //console.log(msgHashValue);
Axel Colin de Verdiere49c08a72012-06-05 23:04:16 -0700332 return (diHashValue == msgHashValue);
333}
334
Wentao Shang882e34e2013-01-05 02:49:51 -0800335
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -0700336RSAKey.prototype.signString = _rsasign_signString;
337
Axel Colin de Verdiere49c08a72012-06-05 23:04:16 -0700338RSAKey.prototype.signByteArray = _rsasign_signByteArray; //@author axelcdv
339RSAKey.prototype.signByteArrayWithSHA256 = _rsasign_signByteArrayWithSHA256; //@author axelcdv
340
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -0700341RSAKey.prototype.signStringWithSHA1 = _rsasign_signStringWithSHA1;
342RSAKey.prototype.signStringWithSHA256 = _rsasign_signStringWithSHA256;
343RSAKey.prototype.sign = _rsasign_signString;
344RSAKey.prototype.signWithSHA1 = _rsasign_signStringWithSHA1;
345RSAKey.prototype.signWithSHA256 = _rsasign_signStringWithSHA256;
346
347
348/*RSAKey.prototype.signStringHEX = _rsasign_signStringHEX;
349RSAKey.prototype.signStringWithSHA1HEX = _rsasign_signStringWithSHA1HEX;
350RSAKey.prototype.signStringWithSHA256HEX = _rsasign_signStringWithSHA256HEX;
351RSAKey.prototype.signHEX = _rsasign_signStringHEX;
352RSAKey.prototype.signWithSHA1HEX = _rsasign_signStringWithSHA1HEX;
353RSAKey.prototype.signWithSHA256HEX = _rsasign_signStringWithSHA256HEX;
354*/
355
Axel Colin de Verdiere49c08a72012-06-05 23:04:16 -0700356RSAKey.prototype.verifyByteArray = _rsasign_verifyByteArray;
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -0700357RSAKey.prototype.verifyString = _rsasign_verifyString;
358RSAKey.prototype.verifyHexSignatureForMessage = _rsasign_verifyHexSignatureForMessage;
359RSAKey.prototype.verify = _rsasign_verifyString;
360RSAKey.prototype.verifyHexSignatureForByteArrayMessage = _rsasign_verifyHexSignatureForMessage;
361
362/*
363RSAKey.prototype.verifyStringHEX = _rsasign_verifyStringHEX;
364RSAKey.prototype.verifyHexSignatureForMessageHEX = _rsasign_verifyHexSignatureForMessageHEX;
365RSAKey.prototype.verifyHEX = _rsasign_verifyStringHEX;
366RSAKey.prototype.verifyHexSignatureForByteArrayMessageHEX = _rsasign_verifyHexSignatureForMessageHEX;
367*/
368
369
370/**
371 * @name RSAKey
372 * @class
373 * @description Tom Wu's RSA Key class and extension
374 */