mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
crypto/rsa: only enforce that de ≡ 1 mod |(ℤ/nℤ)*| in order to load private keys generated by GnuTLS.
Previously we checked that de ≡ 1 mod φ(n). Since φ(n) is a multiple of |(ℤ/nℤ)*|, this encompassed the new check, but it was too strict as keys generated by GnuTLS would be rejected when gcd(p-1,q-1)≠1. (Also updated the error strings in crypto/rsa to contain the package name, which some were missing.) R=golang-dev, r CC=golang-dev https://golang.org/cl/5867043
This commit is contained in:
parent
34ace1043e
commit
22690e6621
3 changed files with 35 additions and 9 deletions
|
|
@ -232,11 +232,11 @@ func VerifyPKCS1v15(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte)
|
||||||
func pkcs1v15HashInfo(hash crypto.Hash, inLen int) (hashLen int, prefix []byte, err error) {
|
func pkcs1v15HashInfo(hash crypto.Hash, inLen int) (hashLen int, prefix []byte, err error) {
|
||||||
hashLen = hash.Size()
|
hashLen = hash.Size()
|
||||||
if inLen != hashLen {
|
if inLen != hashLen {
|
||||||
return 0, nil, errors.New("input must be hashed message")
|
return 0, nil, errors.New("crypto/rsa: input must be hashed message")
|
||||||
}
|
}
|
||||||
prefix, ok := hashPrefixes[hash]
|
prefix, ok := hashPrefixes[hash]
|
||||||
if !ok {
|
if !ok {
|
||||||
return 0, nil, errors.New("unsupported hash function")
|
return 0, nil, errors.New("crypto/rsa: unsupported hash function")
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ func (priv *PrivateKey) Validate() error {
|
||||||
// easy for an attack to generate composites that pass this test.
|
// easy for an attack to generate composites that pass this test.
|
||||||
for _, prime := range priv.Primes {
|
for _, prime := range priv.Primes {
|
||||||
if !prime.ProbablyPrime(20) {
|
if !prime.ProbablyPrime(20) {
|
||||||
return errors.New("prime factor is composite")
|
return errors.New("crypto/rsa: prime factor is composite")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -73,13 +73,20 @@ func (priv *PrivateKey) Validate() error {
|
||||||
modulus.Mul(modulus, prime)
|
modulus.Mul(modulus, prime)
|
||||||
}
|
}
|
||||||
if modulus.Cmp(priv.N) != 0 {
|
if modulus.Cmp(priv.N) != 0 {
|
||||||
return errors.New("invalid modulus")
|
return errors.New("crypto/rsa: invalid modulus")
|
||||||
}
|
}
|
||||||
// Check that e and totient(Πprimes) are coprime.
|
// Check that e and totient(Πprimes) are coprime.
|
||||||
totient := new(big.Int).Set(bigOne)
|
totient := new(big.Int).Set(bigOne)
|
||||||
|
var gcdTotients *big.Int
|
||||||
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)
|
totient.Mul(totient, pminus1)
|
||||||
|
|
||||||
|
if gcdTotients == nil {
|
||||||
|
gcdTotients = pminus1
|
||||||
|
} else {
|
||||||
|
gcdTotients.GCD(nil, nil, gcdTotients, pminus1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
e := big.NewInt(int64(priv.E))
|
e := big.NewInt(int64(priv.E))
|
||||||
gcd := new(big.Int)
|
gcd := new(big.Int)
|
||||||
|
|
@ -87,13 +94,14 @@ func (priv *PrivateKey) Validate() error {
|
||||||
y := new(big.Int)
|
y := new(big.Int)
|
||||||
gcd.GCD(x, y, totient, e)
|
gcd.GCD(x, y, totient, e)
|
||||||
if gcd.Cmp(bigOne) != 0 {
|
if gcd.Cmp(bigOne) != 0 {
|
||||||
return errors.New("invalid public exponent E")
|
return errors.New("crypto/rsa: invalid public exponent E")
|
||||||
}
|
}
|
||||||
// Check that de ≡ 1 (mod totient(Πprimes))
|
// Check that de ≡ 1 mod |ℤ/nℤ| where |ℤ/nℤ| = totient/gcdTotients
|
||||||
de := new(big.Int).Mul(priv.D, e)
|
de := new(big.Int).Mul(priv.D, e)
|
||||||
de.Mod(de, totient)
|
order := new(big.Int).Div(totient, gcdTotients)
|
||||||
|
de.Mod(de, order)
|
||||||
if de.Cmp(bigOne) != 0 {
|
if de.Cmp(bigOne) != 0 {
|
||||||
return errors.New("invalid private exponent D")
|
return errors.New("crypto/rsa: invalid private exponent D")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -118,7 +126,7 @@ func GenerateMultiPrimeKey(random io.Reader, nprimes int, bits int) (priv *Priva
|
||||||
priv.E = 65537
|
priv.E = 65537
|
||||||
|
|
||||||
if nprimes < 2 {
|
if nprimes < 2 {
|
||||||
return nil, errors.New("rsa.GenerateMultiPrimeKey: nprimes must be >= 2")
|
return nil, errors.New("crypto/rsa: GenerateMultiPrimeKey: nprimes must be >= 2")
|
||||||
}
|
}
|
||||||
|
|
||||||
primes := make([]*big.Int, nprimes)
|
primes := make([]*big.Int, nprimes)
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,24 @@ func Test4PrimeKeyGeneration(t *testing.T) {
|
||||||
testKeyBasics(t, priv)
|
testKeyBasics(t, priv)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGnuTLSKey(t *testing.T) {
|
||||||
|
// This is a key generated by `certtool --generate-privkey --bits 128`.
|
||||||
|
// It's such that de ≢ 1 mod φ(n), but is congruent mod the order of
|
||||||
|
// the group.
|
||||||
|
priv := &PrivateKey{
|
||||||
|
PublicKey: PublicKey{
|
||||||
|
N: fromBase10("290684273230919398108010081414538931343"),
|
||||||
|
E: 65537,
|
||||||
|
},
|
||||||
|
D: fromBase10("31877380284581499213530787347443987241"),
|
||||||
|
Primes: []*big.Int{
|
||||||
|
fromBase10("16775196964030542637"),
|
||||||
|
fromBase10("17328218193455850539"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
testKeyBasics(t, priv)
|
||||||
|
}
|
||||||
|
|
||||||
func testKeyBasics(t *testing.T, priv *PrivateKey) {
|
func testKeyBasics(t *testing.T, priv *PrivateKey) {
|
||||||
if err := priv.Validate(); err != nil {
|
if err := priv.Validate(); err != nil {
|
||||||
t.Errorf("Validate() failed: %s", err)
|
t.Errorf("Validate() failed: %s", err)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue