]> Cypherpunks repositories - gostls13.git/commitdiff
crypto/rsa: only enforce that de ≡ 1 mod |(ℤ/nℤ)*| in order to load private keys...
authorAdam Langley <agl@golang.org>
Wed, 4 Apr 2012 16:53:59 +0000 (12:53 -0400)
committerAdam Langley <agl@golang.org>
Wed, 4 Apr 2012 16:53:59 +0000 (12:53 -0400)
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

src/pkg/crypto/rsa/pkcs1v15.go
src/pkg/crypto/rsa/rsa.go
src/pkg/crypto/rsa/rsa_test.go

index 254f4a3da04203ff0a7b5a2b6be4ee667f9d1654..8981074b63a9acc0d4adb2dfd4d334eea854ae11 100644 (file)
@@ -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) {
        hashLen = hash.Size()
        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]
        if !ok {
-               return 0, nil, errors.New("unsupported hash function")
+               return 0, nil, errors.New("crypto/rsa: unsupported hash function")
        }
        return
 }
index ec77e68696b4b366e59079a57117c9b41160b799..6ff89a902f4368e5f05c937fb06de6c67875e575 100644 (file)
@@ -63,7 +63,7 @@ func (priv *PrivateKey) Validate() error {
        // easy for an attack to generate composites that pass this test.
        for _, prime := range priv.Primes {
                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)
        }
        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.
        totient := new(big.Int).Set(bigOne)
+       var gcdTotients *big.Int
        for _, prime := range priv.Primes {
                pminus1 := new(big.Int).Sub(prime, bigOne)
                totient.Mul(totient, pminus1)
+
+               if gcdTotients == nil {
+                       gcdTotients = pminus1
+               } else {
+                       gcdTotients.GCD(nil, nil, gcdTotients, pminus1)
+               }
        }
        e := big.NewInt(int64(priv.E))
        gcd := new(big.Int)
@@ -87,13 +94,14 @@ func (priv *PrivateKey) Validate() error {
        y := new(big.Int)
        gcd.GCD(x, y, totient, e)
        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.Mod(de, totient)
+       order := new(big.Int).Div(totient, gcdTotients)
+       de.Mod(de, order)
        if de.Cmp(bigOne) != 0 {
-               return errors.New("invalid private exponent D")
+               return errors.New("crypto/rsa: invalid private exponent D")
        }
        return nil
 }
@@ -118,7 +126,7 @@ func GenerateMultiPrimeKey(random io.Reader, nprimes int, bits int) (priv *Priva
        priv.E = 65537
 
        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)
index 0fb9875d0440bde4be6a12635674b6a12b0856da..62bbdc4aec3a2113d33ee3c93a7f3ce0c484587a 100644 (file)
@@ -50,6 +50,24 @@ func Test4PrimeKeyGeneration(t *testing.T) {
        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) {
        if err := priv.Validate(); err != nil {
                t.Errorf("Validate() failed: %s", err)