@@ -48,6 +48,13 @@ _RSASIGN_HASHHEXFUNC['ripemd160'] = function(s){return hex_rmd160(s);}; // htt
48
48
//_RSASIGN_HASHHEXFUNC['sha1'] = function(s){return sha1.hex(s);} // http://user1.matsumoto.ne.jp/~goma/js/hash.html
49
49
//_RSASIGN_HASHHEXFUNC['sha256'] = function(s){return sha256.hex;} // http://user1.matsumoto.ne.jp/~goma/js/hash.html
50
50
51
+ var _RSASIGN_HASHRAWFUNC = [ ] ;
52
+ _RSASIGN_HASHRAWFUNC [ 'sha1' ] = function ( s ) { return rstr_sha1 ( s ) ; } ; // http://pajhome.org.uk/crypt/md5/md5.html
53
+ _RSASIGN_HASHRAWFUNC [ 'sha256' ] = function ( s ) { return rstr_sha256 ( s ) ; } // http://pajhome.org.uk/crypt/md5/md5.html
54
+ _RSASIGN_HASHRAWFUNC [ 'sha512' ] = function ( s ) { return rstr_sha512 ( s ) ; } // http://pajhome.org.uk/crypt/md5/md5.html
55
+ _RSASIGN_HASHRAWFUNC [ 'md5' ] = function ( s ) { return rstr_md5 ( s ) ; } ; // http://pajhome.org.uk/crypt/md5/md5.html
56
+ _RSASIGN_HASHRAWFUNC [ 'ripemd160' ] = function ( s ) { return rstr_rmd160 ( s ) ; } ; // http://pajhome.org.uk/crypt/md5/md5.html
57
+
51
58
var _RE_HEXDECONLY = new RegExp ( "" ) ;
52
59
_RE_HEXDECONLY . compile ( "[^0-9a-f]" , "gi" ) ;
53
60
@@ -97,6 +104,92 @@ function _rsasign_signStringWithSHA256(s) {
97
104
return _rsasign_signString . call ( this , s , 'sha256' ) ;
98
105
}
99
106
107
+ // PKCS#1 (PSS) mask generation function
108
+ function pss_mgf1_str ( seed , len , hash )
109
+ {
110
+ var mask = '' , i = 0 ;
111
+
112
+ while ( mask . length < len )
113
+ {
114
+ mask += hash ( seed + String . fromCharCode . apply ( String , [
115
+ ( i & 0xff000000 ) >> 24 ,
116
+ ( i & 0x00ff0000 ) >> 16 ,
117
+ ( i & 0x0000ff00 ) >> 8 ,
118
+ i & 0x000000ff ] ) ) ;
119
+ i += 1 ;
120
+ }
121
+
122
+ return mask ;
123
+ }
124
+
125
+ function _rsasign_signStringPSS ( s , hashAlg , sLen )
126
+ {
127
+ var hashFunc = _RSASIGN_HASHRAWFUNC [ hashAlg ] ;
128
+ var mHash = hashFunc ( s ) ;
129
+ var hLen = mHash . length ;
130
+ var emBits = this . n . bitLength ( ) - 1 ;
131
+ var emLen = Math . ceil ( emBits / 8 ) ;
132
+ var i ;
133
+
134
+ if ( sLen === - 1 )
135
+ {
136
+ sLen = hLen ; // same has hash length
137
+ }
138
+ else if ( ( sLen === - 2 ) || ( sLen === undefined ) )
139
+ {
140
+ sLen = emLen - hLen - 2 ; // maximum
141
+ }
142
+ else if ( sLen < - 2 )
143
+ {
144
+ throw "invalid salt length" ;
145
+ }
146
+
147
+ if ( emLen < ( hLen + sLen + 2 ) )
148
+ {
149
+ throw "data too long" ;
150
+ }
151
+
152
+ var salt = '' ;
153
+
154
+ if ( sLen > 0 )
155
+ {
156
+ salt = new Array ( sLen ) ;
157
+ new SecureRandom ( ) . nextBytes ( salt ) ;
158
+ salt = String . fromCharCode . apply ( String , salt ) ;
159
+ }
160
+
161
+ var H = hashFunc ( '\x00\x00\x00\x00\x00\x00\x00\x00' + mHash + salt ) ;
162
+ var PS = [ ] ;
163
+
164
+ for ( i = 0 ; i < emLen - sLen - hLen - 2 ; i += 1 )
165
+ {
166
+ PS [ i ] = 0x00 ;
167
+ }
168
+
169
+ var DB = String . fromCharCode . apply ( String , PS ) + '\x01' + salt ;
170
+ var dbMask = pss_mgf1_str ( H , DB . length , hashFunc ) ;
171
+ var maskedDB = [ ] ;
172
+
173
+ for ( i = 0 ; i < DB . length ; i += 1 )
174
+ {
175
+ maskedDB [ i ] = DB . charCodeAt ( i ) ^ dbMask . charCodeAt ( i ) ;
176
+ }
177
+
178
+ var mask = ( 0xff00 >> ( 8 * emLen - emBits ) ) & 0xff ;
179
+ maskedDB [ 0 ] &= ~ mask ;
180
+
181
+ for ( i = 0 ; i < hLen ; i ++ )
182
+ {
183
+ maskedDB . push ( H . charCodeAt ( i ) ) ;
184
+ }
185
+
186
+ maskedDB . push ( 0xbc ) ;
187
+
188
+ return _zeroPaddingOfSignature (
189
+ this . doPrivate ( new BigInteger ( maskedDB ) ) . toString ( 16 ) ,
190
+ this . n . bitLength ( ) ) ;
191
+ }
192
+
100
193
// ========================================================================
101
194
// Signature Verification
102
195
// ========================================================================
@@ -178,15 +271,111 @@ function _rsasign_verifyString(sMsg, hSig) {
178
271
return ( diHashValue == msgHashValue ) ;
179
272
}
180
273
274
+ function _rsasign_verifyStringPSS ( sMsg , hSig , hashAlg , sLen )
275
+ {
276
+ if ( hSig . length !== this . n . bitLength ( ) / 4 )
277
+ {
278
+ return false ;
279
+ }
280
+
281
+ var hashFunc = _RSASIGN_HASHRAWFUNC [ hashAlg ] ;
282
+ var mHash = hashFunc ( sMsg ) ;
283
+ var hLen = mHash . length ;
284
+ var emBits = this . n . bitLength ( ) - 1 ;
285
+ var emLen = Math . ceil ( emBits / 8 ) ;
286
+ var i ;
287
+
288
+ if ( sLen === - 1 )
289
+ {
290
+ sLen = hLen ; // same has hash length
291
+ }
292
+ else if ( ( sLen === - 2 ) || ( sLen === undefined ) )
293
+ {
294
+ sLen = emLen - hLen - 2 ; // maximum
295
+ }
296
+ else if ( sLen < - 2 )
297
+ {
298
+ throw "invalid salt length" ;
299
+ }
300
+
301
+ if ( emLen < ( hLen + sLen + 2 ) )
302
+ {
303
+ throw "data too long" ;
304
+ }
305
+
306
+ var em = this . doPublic ( parseBigInt ( hSig , 16 ) ) . toByteArray ( ) ;
307
+
308
+ for ( i = 0 ; i < em . length ; i += 1 )
309
+ {
310
+ em [ i ] &= 0xff ;
311
+ }
312
+
313
+ while ( em . length < emLen )
314
+ {
315
+ em . unshift ( 0 ) ;
316
+ }
317
+
318
+ if ( em [ emLen - 1 ] !== 0xbc )
319
+ {
320
+ throw "encoded message does not end in 0xbc" ;
321
+ }
322
+
323
+ em = String . fromCharCode . apply ( String , em ) ;
324
+
325
+ var maskedDB = em . substr ( 0 , emLen - hLen - 1 ) ;
326
+ var H = em . substr ( maskedDB . length , hLen ) ;
327
+
328
+ var mask = ( 0xff00 >> ( 8 * emLen - emBits ) ) & 0xff ;
329
+
330
+ if ( ( maskedDB . charCodeAt ( 0 ) & mask ) !== 0 )
331
+ {
332
+ throw "bits beyond keysize not zero" ;
333
+ }
334
+
335
+ var dbMask = pss_mgf1_str ( H , maskedDB . length , hashFunc ) ;
336
+ var DB = [ ] ;
337
+
338
+ for ( i = 0 ; i < maskedDB . length ; i += 1 )
339
+ {
340
+ DB [ i ] = maskedDB . charCodeAt ( i ) ^ dbMask . charCodeAt ( i ) ;
341
+ }
342
+
343
+ DB [ 0 ] &= ~ mask ;
344
+
345
+ var checkLen = emLen - hLen - sLen - 2 ;
346
+
347
+ for ( i = 0 ; i < checkLen ; i += 1 )
348
+ {
349
+ if ( DB [ i ] !== 0x00 )
350
+ {
351
+ throw "leftmost octets not zero" ;
352
+ }
353
+ }
354
+
355
+ if ( DB [ checkLen ] !== 0x01 )
356
+ {
357
+ throw "0x01 marker not found" ;
358
+ }
359
+
360
+ return H === hashFunc ( '\x00\x00\x00\x00\x00\x00\x00\x00' + mHash +
361
+ String . fromCharCode . apply ( String , DB . slice ( - sLen ) ) ) ;
362
+ }
363
+
181
364
RSAKey . prototype . signString = _rsasign_signString ;
182
365
RSAKey . prototype . signStringWithSHA1 = _rsasign_signStringWithSHA1 ;
183
366
RSAKey . prototype . signStringWithSHA256 = _rsasign_signStringWithSHA256 ;
184
367
RSAKey . prototype . sign = _rsasign_signString ;
185
368
RSAKey . prototype . signWithSHA1 = _rsasign_signStringWithSHA1 ;
186
369
RSAKey . prototype . signWithSHA256 = _rsasign_signStringWithSHA256 ;
370
+ RSAKey . prototype . signStringPSS = _rsasign_signStringPSS ;
371
+ RSAKey . prototype . signPSS = _rsasign_signStringPSS ;
372
+ RSAKey . SALT_LEN_HLEN = - 1 ;
373
+ RSAKey . SALT_LEN_MAX = - 2 ;
187
374
188
375
RSAKey . prototype . verifyString = _rsasign_verifyString ;
189
376
RSAKey . prototype . verifyHexSignatureForMessage = _rsasign_verifyHexSignatureForMessage ;
190
377
RSAKey . prototype . verify = _rsasign_verifyString ;
191
378
RSAKey . prototype . verifyHexSignatureForByteArrayMessage = _rsasign_verifyHexSignatureForMessage ;
192
-
379
+ RSAKey . prototype . verifyStringPSS = _rsasign_verifyStringPSS ;
380
+ RSAKey . prototype . verifyPSS = _rsasign_verifyStringPSS ;
381
+ RSAKey . SALT_LEN_RECOVER = - 2 ;
0 commit comments