1
1
use crate :: pkcs1v15:: copy_with_left_pad;
2
2
use crate :: internals;
3
- use crate :: hash:: { Hashes , Hash } ;
4
- use crate :: key:: { RSAPrivateKey , PublicKey } ;
3
+ use crate :: key:: { RSAPrivateKey , RSAPublicKey } ;
5
4
use crate :: errors:: { Error , Result } ;
6
5
7
6
use alloc:: vec:: Vec ;
8
7
use num_bigint:: BigUint ;
9
8
use subtle:: ConstantTimeEq ;
10
- use sha2:: { Digest , Sha256 } ;
11
- use sha1:: Sha1 ;
9
+ use digest:: Digest ;
12
10
use rand:: Rng ;
13
11
14
- pub fn verify < K : PublicKey > (
15
- pub_key : & K ,
16
- hash : & Hashes ,
12
+ pub fn verify < H : Digest > (
13
+ pub_key : & RSAPublicKey ,
17
14
hashed : & [ u8 ] ,
18
15
sig : & [ u8 ] ) -> Result < ( ) >
19
16
{
@@ -33,60 +30,51 @@ pub fn verify<K: PublicKey>(
33
30
let mut em = vec ! [ 0 ; em_len] ;
34
31
copy_with_left_pad ( & mut em, & m) ;
35
32
36
- match hash {
37
- Hashes :: SHA1 => {
38
- emsa_pss_verify ( hashed, & mut em, em_bits, None , Sha1 :: new ( ) )
39
- } ,
40
- Hashes :: SHA2_256 => {
41
- emsa_pss_verify ( hashed, & mut em, em_bits, None , Sha256 :: new ( ) )
42
- } ,
43
- _ => unimplemented ! ( )
44
- }
33
+ emsa_pss_verify :: < H > ( hashed, & mut em, em_bits, None )
45
34
}
46
35
47
36
48
37
/// SignPSS calculates the signature of hashed using RSASSA-PSS [1].
49
38
/// Note that hashed must be the result of hashing the input message using the
50
39
/// given hash function. The opts argument may be nil, in which case sensible
51
40
/// defaults are used.
52
- pub fn sign < T : Rng > ( rng : & mut T , priv_key : & RSAPrivateKey , hash : & Hashes , hashed : & [ u8 ] , salt_len : Option < usize > ) -> Result < Vec < u8 > > {
41
+ pub fn sign < T : Rng , H : Digest > ( rng : & mut T , priv_key : & RSAPrivateKey , hashed : & [ u8 ] , salt_len : Option < usize > , blind : bool ) -> Result < Vec < u8 > > {
53
42
let salt_len = salt_len. unwrap_or_else ( || {
54
- ( priv_key. n ( ) . bits ( ) + 7 ) / 8 - 2 - hash . size ( )
43
+ ( priv_key. n ( ) . bits ( ) + 7 ) / 8 - 2 - H :: output_size ( )
55
44
} ) ;
56
45
57
46
let mut salt = vec ! [ 0 ; salt_len] ;
58
47
rng. fill ( & mut salt[ ..] ) ;
59
48
60
- return sign_pss_with_salt ( rng, priv_key, hash , hashed, & salt)
49
+ return sign_pss_with_salt :: < _ , H > ( rng, priv_key, hashed, & salt, blind )
61
50
}
62
51
63
52
64
53
// signPSSWithSalt calculates the signature of hashed using PSS [1] with specified salt.
65
54
// Note that hashed must be the result of hashing the input message using the
66
55
// given hash function. salt is a random sequence of bytes whose length will be
67
56
// later used to verify the signature.
68
- fn sign_pss_with_salt < T : Rng > ( rng : & mut T , priv_key : & RSAPrivateKey , hash : & Hashes , hashed : & [ u8 ] , salt : & [ u8 ] ) -> Result < Vec < u8 > > {
57
+ fn sign_pss_with_salt < T : Rng , H : Digest > ( rng : & mut T , priv_key : & RSAPrivateKey , hashed : & [ u8 ] , salt : & [ u8 ] , blind : bool ) -> Result < Vec < u8 > > {
69
58
let n_bits = priv_key. n ( ) . bits ( ) ;
70
59
let mut em = vec ! [ 0 ; ( ( n_bits - 1 ) + 7 ) / 8 ] ;
71
- match hash {
72
- Hashes :: SHA1 => {
73
- emsa_pss_encode ( & mut em, hashed, n_bits - 1 , salt, Sha1 :: new ( ) ) ?;
74
- } ,
75
- Hashes :: SHA2_256 => {
76
- emsa_pss_encode ( & mut em, hashed, n_bits - 1 , salt, Sha256 :: new ( ) ) ?;
77
- } ,
78
- _ => unimplemented ! ( )
79
- }
60
+ emsa_pss_encode :: < H > ( & mut em, hashed, n_bits - 1 , salt) ?;
80
61
81
- let mut m = BigUint :: from_bytes_be ( & em) ;
82
- let mut c = internals:: decrypt_and_check ( Some ( rng) , priv_key, & m) ?. to_bytes_be ( ) ;
62
+ let m = BigUint :: from_bytes_be ( & em) ;
63
+
64
+ let blind_rng = if blind {
65
+ Some ( rng)
66
+ } else {
67
+ None
68
+ } ;
69
+
70
+ let c = internals:: decrypt_and_check ( blind_rng, priv_key, & m) ?. to_bytes_be ( ) ;
83
71
84
72
let mut s = vec ! [ 0 ; ( n_bits + 7 ) / 8 ] ;
85
73
copy_with_left_pad ( & mut s, & c) ;
86
74
return Ok ( s)
87
75
}
88
76
89
- fn emsa_pss_encode < H : Digest > ( em : & mut [ u8 ] , m_hash : & [ u8 ] , em_bits : usize , salt : & [ u8 ] , mut hash : H ) -> Result < ( ) > {
77
+ fn emsa_pss_encode < H : Digest > ( em : & mut [ u8 ] , m_hash : & [ u8 ] , em_bits : usize , salt : & [ u8 ] ) -> Result < ( ) > {
90
78
// See [1], section 9.1.1
91
79
let h_len = H :: output_size ( ) ;
92
80
let s_len = salt. len ( ) ;
@@ -125,11 +113,13 @@ fn emsa_pss_encode<H: Digest>(em: &mut [u8], m_hash: &[u8], em_bits: usize, salt
125
113
//
126
114
// 6. Let H = Hash(M'), an octet string of length h_len.
127
115
let prefix = [ 0u8 ; 8 ] ;
116
+ let mut hash = H :: new ( ) ;
117
+
128
118
hash. input ( & prefix) ;
129
119
hash. input ( m_hash) ;
130
120
hash. input ( salt) ;
131
121
132
- let hashed = hash. result_reset ( ) ;
122
+ let hashed = hash. result ( ) ;
133
123
h. copy_from_slice ( & hashed) ;
134
124
135
125
// 7. Generate an octet string PS consisting of em_len - s_len - h_len - 2
@@ -143,7 +133,7 @@ fn emsa_pss_encode<H: Digest>(em: &mut [u8], m_hash: &[u8], em_bits: usize, salt
143
133
// 9. Let dbMask = MGF(H, emLen - hLen - 1).
144
134
//
145
135
// 10. Let maskedDB = DB \xor dbMask.
146
- mgf1_xor ( db, & mut hash , & h) ;
136
+ mgf1_xor ( db, & mut H :: new ( ) , & h) ;
147
137
148
138
// 11. Set the leftmost 8 * em_len - em_bits bits of the leftmost octet in
149
139
// maskedDB to zero.
@@ -155,7 +145,7 @@ fn emsa_pss_encode<H: Digest>(em: &mut [u8], m_hash: &[u8], em_bits: usize, salt
155
145
return Ok ( ( ) )
156
146
}
157
147
158
- fn emsa_pss_verify < H : Digest > ( m_hash : & [ u8 ] , em : & mut [ u8 ] , em_bits : usize , s_len : Option < usize > , mut hash : H ) -> Result < ( ) > {
148
+ fn emsa_pss_verify < H : Digest > ( m_hash : & [ u8 ] , em : & mut [ u8 ] , em_bits : usize , s_len : Option < usize > ) -> Result < ( ) > {
159
149
// 1. If the length of M is greater than the input limitation for the
160
150
// hash function (2^61 - 1 octets for SHA-1), output "inconsistent"
161
151
// and stop.
@@ -193,7 +183,7 @@ fn emsa_pss_verify<H: Digest>(m_hash: &[u8], em: &mut [u8], em_bits: usize, s_le
193
183
// 7. Let dbMask = MGF(H, em_len - h_len - 1)
194
184
//
195
185
// 8. Let DB = maskedDB \xor dbMask
196
- mgf1_xor ( db, & mut hash , & * h) ;
186
+ mgf1_xor ( db, & mut H :: new ( ) , & * h) ;
197
187
198
188
199
189
// 9. Set the leftmost 8 * emLen - emBits bits of the leftmost octet in DB
@@ -237,6 +227,7 @@ fn emsa_pss_verify<H: Digest>(m_hash: &[u8], em: &mut [u8], em_bits: usize, s_le
237
227
// 13. Let H' = Hash(M'), an octet string of length hLen.
238
228
let prefix = [ 0u8 ; 8 ] ;
239
229
230
+ let mut hash = H :: new ( ) ;
240
231
hash. input ( prefix) ;
241
232
hash. input ( m_hash) ;
242
233
hash. input ( salt) ;
@@ -283,6 +274,8 @@ fn inc_counter(counter: &mut [u8]) {
283
274
}
284
275
285
276
/// Mask generation function
277
+ ///
278
+ /// Will reset the Digest before returning.
286
279
fn mgf1_xor < T : Digest > ( out : & mut [ u8 ] , digest : & mut T , seed : & [ u8 ] ) {
287
280
let mut counter = vec ! [ 0u8 ; 4 ] ;
288
281
let mut i = 0 ;
@@ -310,8 +303,7 @@ fn mgf1_xor<T: Digest>(out: &mut [u8], digest: &mut T, seed: &[u8]) {
310
303
311
304
#[ cfg( test) ]
312
305
mod test {
313
- use crate :: { PaddingScheme , RSAPrivateKey , RSAPublicKey , PublicKey } ;
314
- use crate :: hash:: Hashes ;
306
+ use crate :: { RSAPrivateKey , RSAPublicKey } ;
315
307
316
308
use num_bigint:: BigUint ;
317
309
use num_traits:: { FromPrimitive , Num } ;
@@ -355,7 +347,7 @@ mod test {
355
347
let sig = hex:: decode ( test[ 1 ] ) . unwrap ( ) ;
356
348
357
349
pub_key
358
- . verify ( PaddingScheme :: PSS , Some ( & Hashes :: SHA1 ) , & digest, & sig)
350
+ . verify_pss :: < Sha1 > ( & digest, & sig)
359
351
. expect ( "failed to verify" ) ;
360
352
}
361
353
}
@@ -369,11 +361,11 @@ mod test {
369
361
for test in & tests {
370
362
let digest = Sha1 :: digest ( test. as_bytes ( ) ) . to_vec ( ) ;
371
363
let sig = priv_key
372
- . sign_blinded ( & mut thread_rng ( ) , PaddingScheme :: PSS , Some ( & Hashes :: SHA1 ) , & digest )
364
+ . sign_pss :: < Sha1 , _ > ( & mut thread_rng ( ) , & digest , None , true )
373
365
. expect ( "failed to sign" ) ;
374
366
375
367
priv_key
376
- . verify ( PaddingScheme :: PSS , Some ( & Hashes :: SHA1 ) , & digest, & sig)
368
+ . verify_pss :: < Sha1 > ( & digest, & sig)
377
369
. expect ( "failed to verify" ) ;
378
370
}
379
371
}
0 commit comments