1
0
mirror of https://github.com/golang/go synced 2024-11-20 04:24:51 -07:00

crypto/rsa: fix Verify for multi-prime keys.

The least common multiple is not totient/gcd.

R=remyoudompheng
CC=golang-dev
https://golang.org/cl/5990045
This commit is contained in:
Adam Langley 2012-04-11 12:57:38 -04:00
parent 7247dcab92
commit 772e8ff458

View File

@ -75,34 +75,22 @@ func (priv *PrivateKey) Validate() error {
if modulus.Cmp(priv.N) != 0 { if modulus.Cmp(priv.N) != 0 {
return errors.New("crypto/rsa: invalid modulus") return errors.New("crypto/rsa: invalid modulus")
} }
// Check that e and totient(Πprimes) are coprime.
totient := new(big.Int).Set(bigOne) // Check that de ≡ 1 mod p-1, for each prime.
var gcdTotients *big.Int // This implies that e is coprime to each p-1 as e has a multiplicative
// inverse. Therefore e is coprime to lcm(p-1,q-1,r-1,...) =
// exponent(/n). It also implies that a^de ≡ a mod p as a^(p-1) ≡ 1
// mod p. Thus a^de ≡ a mod n for all a coprime to n, as required.
congruence := new(big.Int)
de := new(big.Int).SetInt64(int64(priv.E))
de.Mul(de, priv.D)
for _, prime := range priv.Primes { for _, prime := range priv.Primes {
pminus1 := new(big.Int).Sub(prime, bigOne) pminus1 := new(big.Int).Sub(prime, bigOne)
totient.Mul(totient, pminus1) congruence.Mod(de, pminus1)
if congruence.Cmp(bigOne) != 0 {
if gcdTotients == nil { return errors.New("crypto/rsa: invalid exponents")
gcdTotients = pminus1
} else {
gcdTotients.GCD(nil, nil, gcdTotients, pminus1)
} }
} }
e := big.NewInt(int64(priv.E))
gcd := new(big.Int)
x := new(big.Int)
y := new(big.Int)
gcd.GCD(x, y, totient, e)
if gcd.Cmp(bigOne) != 0 {
return errors.New("crypto/rsa: invalid public exponent E")
}
// Check that de ≡ 1 mod |/n| where |/n| = totient/gcdTotients
de := new(big.Int).Mul(priv.D, e)
order := new(big.Int).Div(totient, gcdTotients)
de.Mod(de, order)
if de.Cmp(bigOne) != 0 {
return errors.New("crypto/rsa: invalid private exponent D")
}
return nil return nil
} }