1
1
//! Generic RSA implementation
2
2
3
- use alloc:: borrow:: Cow ;
4
3
use alloc:: vec:: Vec ;
5
4
use crypto_bigint:: modular:: BoxedResidueParams ;
6
- use crypto_bigint:: { BoxedUint , NonZero } ;
7
- use num_bigint:: { BigInt , BigUint , IntoBigInt , IntoBigUint , ModInverse , RandBigInt , ToBigInt } ;
5
+ use crypto_bigint:: { BoxedUint , RandomMod } ;
6
+ use num_bigint:: { BigUint , IntoBigInt , IntoBigUint , ModInverse , ToBigInt } ;
8
7
use num_integer:: { sqrt, Integer } ;
9
8
use num_traits:: { FromPrimitive , One , Pow , Signed , Zero as _} ;
10
9
use rand_core:: CryptoRngCore ;
@@ -14,7 +13,7 @@ use zeroize::{Zeroize, Zeroizing};
14
13
use crate :: errors:: { Error , Result } ;
15
14
use crate :: key:: { reduce, to_biguint, to_uint} ;
16
15
use crate :: traits:: keys:: { PrivateKeyPartsNew , PublicKeyPartsNew } ;
17
- use crate :: traits:: { PrivateKeyParts , PublicKeyParts } ;
16
+ use crate :: traits:: PublicKeyParts ;
18
17
19
18
/// ⚠️ Raw RSA encryption of m with the public key. No padding is performed.
20
19
///
@@ -38,25 +37,35 @@ pub fn rsa_encrypt<K: PublicKeyParts>(key: &K, m: &BigUint) -> Result<BigUint> {
38
37
#[ inline]
39
38
pub fn rsa_decrypt < R : CryptoRngCore + ?Sized > (
40
39
mut rng : Option < & mut R > ,
41
- priv_key : & impl PrivateKeyParts ,
42
- c : & BigUint ,
40
+ priv_key : & impl PrivateKeyPartsNew ,
41
+ c_orig : & BigUint ,
43
42
) -> Result < BigUint > {
44
- if c >= & priv_key. n ( ) {
43
+ // convert to crypto bigint
44
+ let c = to_uint ( c_orig. clone ( ) ) ;
45
+ let n = priv_key. n ( ) ;
46
+ let d = priv_key. d ( ) ;
47
+
48
+ if c >= * * n {
45
49
return Err ( Error :: Decryption ) ;
46
50
}
47
51
48
- if priv_key. n ( ) . is_zero ( ) {
52
+ // TODO: is this fine?
53
+ if n. is_zero ( ) . into ( ) {
49
54
return Err ( Error :: Decryption ) ;
50
55
}
51
56
52
57
let mut ir = None ;
53
58
59
+ let n_params = priv_key
60
+ . residue_params ( )
61
+ . cloned ( )
62
+ . unwrap_or_else ( || BoxedResidueParams :: new ( n. clone ( ) . get ( ) ) . unwrap ( ) ) ;
54
63
let c = if let Some ( ref mut rng) = rng {
55
- let ( blinded, unblinder) = blind ( rng, priv_key, c ) ;
64
+ let ( blinded, unblinder) = blind ( rng, priv_key, & c , & n_params ) ;
56
65
ir = Some ( unblinder) ;
57
- Cow :: Owned ( blinded)
66
+ blinded
58
67
} else {
59
- Cow :: Borrowed ( c )
68
+ c
60
69
} ;
61
70
62
71
let dp = priv_key. dp ( ) ;
@@ -68,19 +77,21 @@ pub fn rsa_decrypt<R: CryptoRngCore + ?Sized>(
68
77
( Some ( dp) , Some ( dq) , Some ( qinv) , Some ( crt_values) ) => {
69
78
// We have the precalculated values needed for the CRT.
70
79
71
- let p = & priv_key. primes ( ) [ 0 ] ;
72
- let q = & priv_key. primes ( ) [ 1 ] ;
80
+ let dp = to_biguint ( dp) ;
81
+ let dq = to_biguint ( dq) ;
82
+ let qinv = to_biguint ( qinv) . to_bigint ( ) . unwrap ( ) ;
83
+ let p = to_biguint ( & priv_key. primes ( ) [ 0 ] ) ;
84
+ let q = to_biguint ( & priv_key. primes ( ) [ 1 ] ) ;
73
85
74
- let mut m = c . modpow ( & dp, p) . into_bigint ( ) . unwrap ( ) ;
75
- let mut m2 = c . modpow ( & dq, q) . into_bigint ( ) . unwrap ( ) ;
86
+ let mut m = c_orig . modpow ( & dp, & p) . into_bigint ( ) . unwrap ( ) ;
87
+ let mut m2 = c_orig . modpow ( & dq, & q) . into_bigint ( ) . unwrap ( ) ;
76
88
77
89
m -= & m2;
78
90
79
91
let mut primes: Vec < _ > = priv_key
80
92
. primes ( )
81
93
. iter ( )
82
- . map ( ToBigInt :: to_bigint)
83
- . map ( Option :: unwrap)
94
+ . map ( |p| to_biguint ( p) . to_bigint ( ) . unwrap ( ) )
84
95
. collect ( ) ;
85
96
86
97
while m. is_negative ( ) {
@@ -91,17 +102,17 @@ pub fn rsa_decrypt<R: CryptoRngCore + ?Sized>(
91
102
m *= & primes[ 1 ] ;
92
103
m += & m2;
93
104
94
- let mut c = c . into_owned ( ) . into_bigint ( ) . unwrap ( ) ;
105
+ let mut c = c_orig . to_bigint ( ) . unwrap ( ) ;
95
106
for ( i, value) in crt_values. iter ( ) . enumerate ( ) {
96
107
let prime = & primes[ 2 + i] ;
97
- m2 = c. modpow ( & value. exp , prime) ;
108
+ m2 = c. modpow ( & to_biguint ( & value. exp ) . to_bigint ( ) . unwrap ( ) , prime) ;
98
109
m2 -= & m;
99
- m2 *= & value. coeff ;
110
+ m2 *= & to_biguint ( & value. coeff ) . to_bigint ( ) . unwrap ( ) ;
100
111
m2 %= prime;
101
112
while m2. is_negative ( ) {
102
113
m2 += prime;
103
114
}
104
- m2 *= & value. r ;
115
+ m2 *= & to_biguint ( & value. r ) . to_bigint ( ) . unwrap ( ) ;
105
116
m += & m2;
106
117
}
107
118
@@ -113,17 +124,21 @@ pub fn rsa_decrypt<R: CryptoRngCore + ?Sized>(
113
124
c. zeroize ( ) ;
114
125
m2. zeroize ( ) ;
115
126
116
- m. into_biguint ( ) . expect ( "failed to decrypt" )
127
+ to_uint ( m. into_biguint ( ) . expect ( "failed to decrypt" ) )
128
+ }
129
+ _ => {
130
+ let c = reduce ( & c, n_params) ;
131
+ c. pow ( & d) . retrieve ( )
117
132
}
118
- _ => c. modpow ( & priv_key. d ( ) , & priv_key. n ( ) ) ,
119
133
} ;
120
134
121
135
match ir {
122
136
Some ( ref ir) => {
123
137
// unblind
124
- Ok ( unblind ( priv_key, & m, ir) )
138
+ let res = to_biguint ( & unblind ( priv_key, & m, ir) ) ;
139
+ Ok ( res)
125
140
}
126
- None => Ok ( m ) ,
141
+ None => Ok ( to_biguint ( & m ) ) ,
127
142
}
128
143
}
129
144
@@ -138,29 +153,11 @@ pub fn rsa_decrypt<R: CryptoRngCore + ?Sized>(
138
153
/// or signature scheme. See the [module-level documentation][crate::hazmat] for more information.
139
154
#[ inline]
140
155
pub fn rsa_decrypt_and_check < R : CryptoRngCore + ?Sized > (
141
- priv_key : & impl PrivateKeyParts ,
142
- rng : Option < & mut R > ,
143
- c : & BigUint ,
144
- ) -> Result < BigUint > {
145
- let m = rsa_decrypt ( rng, priv_key, c) ?;
146
-
147
- // In order to defend against errors in the CRT computation, m^e is
148
- // calculated, which should match the original ciphertext.
149
- let check = rsa_encrypt ( priv_key, & m) ?;
150
-
151
- if c != & check {
152
- return Err ( Error :: Internal ) ;
153
- }
154
-
155
- Ok ( m)
156
- }
157
-
158
- pub fn rsa_decrypt_and_check_new < R : CryptoRngCore + ?Sized > (
159
156
priv_key : & impl PrivateKeyPartsNew ,
160
157
rng : Option < & mut R > ,
161
158
c : & BigUint ,
162
159
) -> Result < BigUint > {
163
- let m = rsa_decrypt_new ( rng, priv_key, c) ?;
160
+ let m = rsa_decrypt ( rng, priv_key, c) ?;
164
161
165
162
// In order to defend against errors in the CRT computation, m^e is
166
163
// calculated, which should match the original ciphertext.
@@ -174,38 +171,40 @@ pub fn rsa_decrypt_and_check_new<R: CryptoRngCore + ?Sized>(
174
171
}
175
172
176
173
/// Returns the blinded c, along with the unblinding factor.
177
- fn blind < R : CryptoRngCore , K : PublicKeyParts > (
174
+ fn blind < R : CryptoRngCore , K : PublicKeyPartsNew > (
178
175
rng : & mut R ,
179
176
key : & K ,
180
- c : & BigUint ,
181
- ) -> ( BigUint , BigUint ) {
177
+ c : & BoxedUint ,
178
+ n_params : & BoxedResidueParams ,
179
+ ) -> ( BoxedUint , BoxedUint ) {
182
180
// Blinding involves multiplying c by r^e.
183
181
// Then the decryption operation performs (m^e * r^e)^d mod n
184
182
// which equals mr mod n. The factor of r can then be removed
185
183
// by multiplying by the multiplicative inverse of r.
186
184
187
- let mut r: BigUint ;
188
- let mut ir: Option < BigInt > ;
185
+ let mut r: BoxedUint ;
186
+ let mut ir: CtOption < BoxedUint > ;
189
187
let unblinder;
190
188
loop {
191
- r = rng. gen_biguint_below ( & key. n ( ) ) ;
192
- if r. is_zero ( ) {
193
- r = BigUint :: one ( ) ;
189
+ // TODO: use constant time gen
190
+ r = BoxedUint :: random_mod ( rng, key. n ( ) ) ;
191
+ // TODO: correct mapping
192
+ if r. is_zero ( ) . into ( ) {
193
+ r = BoxedUint :: one ( ) ;
194
194
}
195
- ir = r. clone ( ) . mod_inverse ( key. n ( ) ) ;
196
- if let Some ( ir ) = ir {
197
- if let Some ( ub ) = ir . into_biguint ( ) {
198
- unblinder = ub ;
199
- break ;
200
- }
195
+ ir = r. inv_mod ( key. n ( ) ) ;
196
+
197
+ // TODO: constant time?
198
+ if let Some ( ir ) = ir . into ( ) {
199
+ unblinder = ir ;
200
+ break ;
201
201
}
202
202
}
203
203
204
204
let c = {
205
- let mut rpowe = r. modpow ( & key. e ( ) , & key. n ( ) ) ; // N != 0
206
- let mut c = c * & rpowe;
207
- c %= key. n ( ) ;
208
-
205
+ let r = reduce ( & r, n_params. clone ( ) ) ;
206
+ let mut rpowe = r. pow ( key. e ( ) ) . retrieve ( ) ;
207
+ let c = c. mul_mod ( & rpowe, key. n ( ) ) ;
209
208
rpowe. zeroize ( ) ;
210
209
211
210
c
@@ -215,8 +214,8 @@ fn blind<R: CryptoRngCore, K: PublicKeyParts>(
215
214
}
216
215
217
216
/// Given an m and and unblinding factor, unblind the m.
218
- fn unblind ( key : & impl PublicKeyParts , m : & BigUint , unblinder : & BigUint ) -> BigUint {
219
- ( m * unblinder) % key. n ( )
217
+ fn unblind ( key : & impl PublicKeyPartsNew , m : & BoxedUint , unblinder : & BoxedUint ) -> BoxedUint {
218
+ m . mul_mod ( unblinder, key. n ( ) )
220
219
}
221
220
222
221
/// The following (deterministic) algorithm also recovers the prime factors `p` and `q` of a modulus `n`, given the
@@ -326,99 +325,6 @@ pub(crate) fn compute_private_exponent_carmicheal(
326
325
}
327
326
}
328
327
329
- fn blind_new < R : CryptoRngCore , K : PublicKeyPartsNew > (
330
- rng : & mut R ,
331
- key : & K ,
332
- c : & BoxedUint ,
333
- n_params : & BoxedResidueParams ,
334
- ) -> ( BoxedUint , BoxedUint ) {
335
- let mut r: BoxedUint ;
336
- let mut ir: CtOption < BoxedUint > ;
337
- let unblinder;
338
- loop {
339
- // TODO: use constant time gen
340
- r = to_uint ( rng. gen_biguint_below ( & to_biguint ( & key. n ( ) ) ) ) ;
341
- // TODO: correct mapping
342
- if r. is_zero ( ) . into ( ) {
343
- r = BoxedUint :: one ( ) ;
344
- }
345
- ir = r. inv_mod ( key. n ( ) ) ;
346
-
347
- // TODO: constant time?
348
- if let Some ( ir) = ir. into ( ) {
349
- unblinder = ir;
350
- break ;
351
- }
352
- }
353
-
354
- let c = {
355
- let r = reduce ( & r, n_params. clone ( ) ) ;
356
- let mut rpowe = r. pow ( key. e ( ) ) . retrieve ( ) ;
357
-
358
- let c = c. wrapping_mul ( & rpowe) ;
359
- let c = c. rem_vartime ( key. n ( ) ) ;
360
-
361
- rpowe. zeroize ( ) ;
362
-
363
- c
364
- } ;
365
-
366
- ( c, unblinder)
367
- }
368
-
369
- fn unblind_new ( key : & impl PublicKeyPartsNew , m : & BoxedUint , unblinder : & BoxedUint ) -> BoxedUint {
370
- let a = m. wrapping_mul ( unblinder) ;
371
- a. rem_vartime ( key. n ( ) )
372
- }
373
-
374
- pub fn rsa_decrypt_new < R : CryptoRngCore + ?Sized > (
375
- mut rng : Option < & mut R > ,
376
- priv_key : & impl PrivateKeyPartsNew ,
377
- c : & BigUint ,
378
- ) -> Result < BigUint > {
379
- // convert to crypto bigint
380
- let c = to_uint ( c. clone ( ) ) ;
381
- let n = priv_key. n ( ) ;
382
- let d = priv_key. d ( ) ;
383
-
384
- if c >= * * n {
385
- return Err ( Error :: Decryption ) ;
386
- }
387
-
388
- // TODO: is this fine?
389
- if n. is_zero ( ) . into ( ) {
390
- return Err ( Error :: Decryption ) ;
391
- }
392
-
393
- let mut ir = None ;
394
-
395
- let n_params = priv_key
396
- . residue_params ( )
397
- . cloned ( )
398
- . unwrap_or_else ( || BoxedResidueParams :: new ( n. clone ( ) . get ( ) ) . unwrap ( ) ) ;
399
-
400
- let c = if let Some ( ref mut rng) = rng {
401
- let ( blinded, unblinder) = blind_new ( rng, priv_key, & c, & n_params) ;
402
- ir = Some ( unblinder) ;
403
- blinded
404
- } else {
405
- c
406
- } ;
407
-
408
- // TODO: fast path with precalculated values;
409
- let c = reduce ( & c, n_params) ;
410
- let m = c. pow ( & d) . retrieve ( ) ;
411
-
412
- match ir {
413
- Some ( ref ir) => {
414
- // unblind
415
- let m = unblind_new ( priv_key, & m, ir) ;
416
- Ok ( to_biguint ( & m) )
417
- }
418
- None => Ok ( to_biguint ( & m) ) ,
419
- }
420
- }
421
-
422
328
#[ cfg( test) ]
423
329
mod tests {
424
330
use num_traits:: FromPrimitive ;
0 commit comments