|
20 | 20 | // Decrypter and Signer interfaces from the crypto package.
|
21 | 21 | //
|
22 | 22 | // Operations involving private keys are implemented using constant-time
|
23 |
| -// algorithms, except for [GenerateKey], [PrivateKey.Precompute], and |
24 |
| -// [PrivateKey.Validate]. |
| 23 | +// algorithms, except for [GenerateKey] and [PrivateKey.Precompute]. |
25 | 24 | //
|
26 | 25 | // # Minimum key size
|
27 | 26 | //
|
@@ -236,34 +235,67 @@ func (priv *PrivateKey) Validate() error {
|
236 | 235 | return errors.New("crypto/rsa: public exponent too large")
|
237 | 236 | }
|
238 | 237 |
|
239 |
| - // Check that Πprimes == n. |
240 |
| - modulus := new(big.Int).Set(bigOne) |
241 |
| - for _, prime := range priv.Primes { |
242 |
| - // Any primes ≤ 1 will cause divide-by-zero panics later. |
243 |
| - if prime.Cmp(bigOne) <= 0 { |
244 |
| - return errors.New("crypto/rsa: invalid prime value") |
245 |
| - } |
246 |
| - modulus.Mul(modulus, prime) |
| 238 | + N, err := bigmod.NewModulus(pub.N.Bytes()) |
| 239 | + if err != nil { |
| 240 | + return fmt.Errorf("crypto/rsa: invalid public modulus: %v", err) |
247 | 241 | }
|
248 |
| - if modulus.Cmp(priv.N) != 0 { |
249 |
| - return errors.New("crypto/rsa: invalid modulus") |
| 242 | + d, err := bigmod.NewNat().SetBytes(priv.D.Bytes(), N) |
| 243 | + if err != nil { |
| 244 | + return fmt.Errorf("crypto/rsa: invalid private exponent: %v", err) |
| 245 | + } |
| 246 | + one, err := bigmod.NewNat().SetUint(1, N) |
| 247 | + if err != nil { |
| 248 | + return fmt.Errorf("crypto/rsa: internal error: %v", err) |
250 | 249 | }
|
251 | 250 |
|
252 |
| - // Check that de ≡ 1 mod p-1, for each prime. |
253 |
| - // This implies that e is coprime to each p-1 as e has a multiplicative |
254 |
| - // inverse. Therefore e is coprime to lcm(p-1,q-1,r-1,...) = |
255 |
| - // exponent(ℤ/nℤ). It also implies that a^de ≡ a mod p as a^(p-1) ≡ 1 |
256 |
| - // mod p. Thus a^de ≡ a mod n for all a coprime to n, as required. |
257 |
| - congruence := new(big.Int) |
258 |
| - de := new(big.Int).SetInt64(int64(priv.E)) |
259 |
| - de.Mul(de, priv.D) |
| 251 | + Π := bigmod.NewNat().ExpandFor(N) |
260 | 252 | for _, prime := range priv.Primes {
|
261 |
| - pminus1 := new(big.Int).Sub(prime, bigOne) |
262 |
| - congruence.Mod(de, pminus1) |
263 |
| - if congruence.Cmp(bigOne) != 0 { |
| 253 | + p, err := bigmod.NewNat().SetBytes(prime.Bytes(), N) |
| 254 | + if err != nil { |
| 255 | + return fmt.Errorf("crypto/rsa: invalid prime: %v", err) |
| 256 | + } |
| 257 | + if p.IsZero() == 1 { |
| 258 | + return errors.New("crypto/rsa: invalid prime") |
| 259 | + } |
| 260 | + Π.Mul(p, N) |
| 261 | + |
| 262 | + // Check that de ≡ 1 mod p-1, for each prime. |
| 263 | + // This implies that e is coprime to each p-1 as e has a multiplicative |
| 264 | + // inverse. Therefore e is coprime to lcm(p-1,q-1,r-1,...) = |
| 265 | + // exponent(ℤ/nℤ). It also implies that a^de ≡ a mod p as a^(p-1) ≡ 1 |
| 266 | + // mod p. Thus a^de ≡ a mod n for all a coprime to n, as required. |
| 267 | + |
| 268 | + p.Sub(one, N) |
| 269 | + if p.IsZero() == 1 { |
| 270 | + return errors.New("crypto/rsa: invalid prime") |
| 271 | + } |
| 272 | + pMinus1, err := bigmod.NewModulus(p.Bytes(N)) |
| 273 | + if err != nil { |
| 274 | + return fmt.Errorf("crypto/rsa: internal error: %v", err) |
| 275 | + } |
| 276 | + |
| 277 | + e, err := bigmod.NewNat().SetUint(uint(pub.E), pMinus1) |
| 278 | + if err != nil { |
| 279 | + return fmt.Errorf("crypto/rsa: invalid public exponent: %v", err) |
| 280 | + } |
| 281 | + one, err := bigmod.NewNat().SetUint(1, pMinus1) |
| 282 | + if err != nil { |
| 283 | + return fmt.Errorf("crypto/rsa: internal error: %v", err) |
| 284 | + } |
| 285 | + |
| 286 | + de := bigmod.NewNat() |
| 287 | + de.Mod(d, pMinus1) |
| 288 | + de.Mul(e, pMinus1) |
| 289 | + de.Sub(one, pMinus1) |
| 290 | + if de.IsZero() != 1 { |
264 | 291 | return errors.New("crypto/rsa: invalid exponents")
|
265 | 292 | }
|
266 | 293 | }
|
| 294 | + // Check that Πprimes == n. |
| 295 | + if Π.IsZero() != 1 { |
| 296 | + return errors.New("crypto/rsa: invalid modulus") |
| 297 | + } |
| 298 | + |
267 | 299 | return nil
|
268 | 300 | }
|
269 | 301 |
|
@@ -450,6 +482,10 @@ NextSetOfPrimes:
|
450 | 482 | }
|
451 | 483 |
|
452 | 484 | priv.Precompute()
|
| 485 | + if err := priv.Validate(); err != nil { |
| 486 | + return nil, err |
| 487 | + } |
| 488 | + |
453 | 489 | return priv, nil
|
454 | 490 | }
|
455 | 491 |
|
|
0 commit comments