package rsa
import (
+ "bytes"
"crypto/internal/fips140"
"crypto/internal/fips140/bigmod"
"errors"
//
// All values are in big-endian byte slice format, and may have leading zeros
// or be shorter if leading zeroes were trimmed.
-//
-// N, e, d, P, and Q are required. dP, dQ, and qInv can be nil and will be
-// precomputed if missing.
-func NewPrivateKey(N []byte, e int, d, P, Q, dP, dQ, qInv []byte) (*PrivateKey, error) {
+func NewPrivateKey(N []byte, e int, d, P, Q []byte) (*PrivateKey, error) {
n, err := bigmod.NewModulus(N)
if err != nil {
return nil, err
if err != nil {
return nil, err
}
- // TODO(filippo): implement CRT computation. For now, NewPrivateKey is
- // always called with CRT values.
- if dP == nil || dQ == nil || qInv == nil {
- panic("crypto/internal/fips140/rsa: internal error: missing CRT parameters")
+ return newPrivateKey(n, e, dN, p, q)
+}
+
+func newPrivateKey(n *bigmod.Modulus, e int, d *bigmod.Nat, p, q *bigmod.Modulus) (*PrivateKey, error) {
+ pMinusOne := p.Nat().SubOne(p)
+ pMinusOneMod, err := bigmod.NewModulus(pMinusOne.Bytes(p))
+ if err != nil {
+ return nil, err
}
- qInvN, err := bigmod.NewNat().SetBytes(qInv, p)
+ dP := bigmod.NewNat().Mod(d, pMinusOneMod).Bytes(pMinusOneMod)
+
+ qMinusOne := q.Nat().SubOne(q)
+ qMinusOneMod, err := bigmod.NewModulus(qMinusOne.Bytes(q))
if err != nil {
return nil, err
}
+ dQ := bigmod.NewNat().Mod(d, qMinusOneMod).Bytes(qMinusOneMod)
+
+ // Constant-time modular inversion with prime modulus by Fermat's Little
+ // Theorem: qInv = q⁻¹ mod p = q^(p-2) mod p.
+ if p.Nat().IsOdd() == 0 {
+ // [bigmod.Nat.Exp] requires an odd modulus.
+ return nil, errors.New("crypto/rsa: p is even")
+ }
+ pMinusTwo := p.Nat().SubOne(p).SubOne(p).Bytes(p)
+ qInv := bigmod.NewNat().Mod(q.Nat(), p)
+ qInv.Exp(qInv, pMinusTwo, p)
+
pk := &PrivateKey{
pub: PublicKey{
N: n, E: e,
},
- d: dN, p: p, q: q,
- dP: dP, dQ: dQ, qInv: qInvN,
+ d: d, p: p, q: q,
+ dP: dP, dQ: dQ, qInv: qInv,
}
- if err := checkPublicKey(&pk.pub); err != nil {
+ if err := checkPrivateKey(pk); err != nil {
return nil, err
}
return pk, nil
},
d: dN,
}
- if err := checkPublicKey(&pk.pub); err != nil {
+ if err := checkPrivateKey(pk); err != nil {
return nil, err
}
return pk, nil
}
+// Export returns the key parameters in big-endian byte slice format.
+//
+// P, Q, dP, dQ, and qInv may be nil if the key was created with
+// NewPrivateKeyWithoutCRT.
+func (priv *PrivateKey) Export() (N []byte, e int, d, P, Q, dP, dQ, qInv []byte) {
+ N = priv.pub.N.Nat().Bytes(priv.pub.N)
+ e = priv.pub.E
+ d = priv.d.Bytes(priv.pub.N)
+ if priv.dP == nil {
+ return
+ }
+ P = priv.p.Nat().Bytes(priv.p)
+ Q = priv.q.Nat().Bytes(priv.q)
+ dP = bytes.Clone(priv.dP)
+ dQ = bytes.Clone(priv.dQ)
+ qInv = priv.qInv.Bytes(priv.p)
+ return
+}
+
+func checkPrivateKey(priv *PrivateKey) error {
+ if err := checkPublicKey(&priv.pub); err != nil {
+ return err
+ }
+
+ if priv.dP == nil {
+ return nil
+ }
+
+ N := priv.pub.N
+ Π := bigmod.NewNat().ExpandFor(N)
+ for _, prime := range []*bigmod.Modulus{priv.p, priv.q} {
+ p := prime.Nat().ExpandFor(N)
+ if p.IsZero() == 1 || p.IsOne() == 1 {
+ return errors.New("crypto/rsa: invalid prime")
+ }
+ Π.Mul(p, N)
+
+ // Check that de ≡ 1 mod p-1, for each prime.
+ // 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.
+
+ pMinus1, err := bigmod.NewModulus(p.SubOne(N).Bytes(N))
+ if err != nil {
+ return errors.New("crypto/rsa: invalid prime")
+ }
+
+ e := bigmod.NewNat().SetUint(uint(priv.pub.E)).ExpandFor(pMinus1)
+
+ de := bigmod.NewNat()
+ de.Mod(priv.d, pMinus1)
+ de.Mul(e, pMinus1)
+ if de.IsOne() != 1 {
+ return errors.New("crypto/rsa: invalid exponents")
+ }
+ }
+ // Check that Πprimes == n.
+ if Π.IsZero() != 1 {
+ return errors.New("crypto/rsa: invalid modulus")
+ }
+
+ return nil
+}
+
func checkPublicKey(pub *PublicKey) error {
if pub.N == nil {
return errors.New("crypto/rsa: missing public modulus")
// Decrypter and Signer interfaces from the crypto package.
//
// Operations involving private keys are implemented using constant-time
-// algorithms, except for [GenerateKey] and [PrivateKey.Precompute].
+// algorithms, except for [GenerateKey] and for some operations involving
+// deprecated multi-prime keys.
//
// # Minimum key size
//
// Validate performs basic sanity checks on the key.
// It returns nil if the key is valid, or else an error describing a problem.
+//
+// It runs faster on valid keys if run after [Precompute].
func (priv *PrivateKey) Validate() error {
- pub := &priv.PublicKey
- if pub.N == nil {
- return errors.New("crypto/rsa: missing public modulus")
- }
- if pub.N.Bit(0) == 0 {
- return errors.New("crypto/rsa: public modulus is even")
- }
- if pub.E < 2 {
- return errors.New("crypto/rsa: public exponent is less than 2")
- }
- if pub.E&1 == 0 {
- return errors.New("crypto/rsa: public exponent is even")
- }
- if pub.E > 1<<31-1 {
- return errors.New("crypto/rsa: public exponent too large")
- }
-
- N, err := bigmod.NewModulus(pub.N.Bytes())
- if err != nil {
- return fmt.Errorf("crypto/rsa: invalid public modulus: %v", err)
- }
- d, err := bigmod.NewNat().SetBytes(priv.D.Bytes(), N)
- if err != nil {
- return fmt.Errorf("crypto/rsa: invalid private exponent: %v", err)
- }
-
- Π := bigmod.NewNat().ExpandFor(N)
- for _, prime := range priv.Primes {
- p, err := bigmod.NewNat().SetBytes(prime.Bytes(), N)
- if err != nil {
- return fmt.Errorf("crypto/rsa: invalid prime: %v", err)
- }
- if p.IsZero() == 1 || p.IsOne() == 1 {
- return errors.New("crypto/rsa: invalid prime")
- }
- Π.Mul(p, N)
-
- // Check that de ≡ 1 mod p-1, for each prime.
- // 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.
-
- pMinus1, err := bigmod.NewModulus(p.SubOne(N).Bytes(N))
- if err != nil {
- return fmt.Errorf("crypto/rsa: internal error: %v", err)
- }
-
- e, err := bigmod.NewNat().SetUint(uint(pub.E), pMinus1)
- if err != nil {
- return fmt.Errorf("crypto/rsa: invalid public exponent: %v", err)
- }
-
- de := bigmod.NewNat()
- de.Mod(d, pMinus1)
- de.Mul(e, pMinus1)
- if de.IsOne() != 1 {
- return errors.New("crypto/rsa: invalid exponents")
- }
+ // We can operate on keys based on d alone, but it isn't possible to encode
+ // with [crypto/x509.MarshalPKCS1PrivateKey], which unfortunately doesn't
+ // return an error.
+ if len(priv.Primes) < 2 {
+ return errors.New("crypto/rsa: missing primes")
}
- // Check that Πprimes == n.
- if Π.IsZero() != 1 {
- return errors.New("crypto/rsa: invalid modulus")
+ // If Precomputed.fips is set, then the key has been validated by
+ // [rsa.NewPrivateKey] or [rsa.NewPrivateKeyWithoutCRT].
+ if priv.Precomputed.fips != nil {
+ return nil
}
-
- return nil
+ _, err := priv.precompute()
+ return err
}
// rsa1024min is a GODEBUG that re-enables weak RSA keys if set to "0".
var ErrVerification = errors.New("crypto/rsa: verification error")
// Precompute performs some calculations that speed up private key operations
-// in the future.
+// in the future. It is safe to run on non-validated private keys.
func (priv *PrivateKey) Precompute() {
if priv.Precomputed.fips != nil {
return
}
- if len(priv.Primes) < 2 {
- priv.Precomputed.fips, _ = rsa.NewPrivateKeyWithoutCRT(
- priv.N.Bytes(), priv.E, priv.D.Bytes())
+ precomputed, err := priv.precompute()
+ if err != nil {
+ // We don't have a way to report errors, so just leave the key
+ // unmodified. Validate will re-run precompute.
return
}
+ priv.Precomputed = precomputed
+}
+
+func (priv *PrivateKey) precompute() (PrecomputedValues, error) {
+ var precomputed PrecomputedValues
+
+ if priv.N == nil {
+ return precomputed, errors.New("crypto/rsa: missing public modulus")
+ }
+ if priv.D == nil {
+ return precomputed, errors.New("crypto/rsa: missing private exponent")
+ }
+ if len(priv.Primes) != 2 {
+ return priv.precomputeLegacy()
+ }
+ if priv.Primes[0] == nil {
+ return precomputed, errors.New("crypto/rsa: prime P is nil")
+ }
+ if priv.Primes[1] == nil {
+ return precomputed, errors.New("crypto/rsa: prime Q is nil")
+ }
+
+ k, err := rsa.NewPrivateKey(priv.N.Bytes(), priv.E, priv.D.Bytes(),
+ priv.Primes[0].Bytes(), priv.Primes[1].Bytes())
+ if err != nil {
+ return precomputed, err
+ }
- priv.Precomputed.Dp = new(big.Int).Sub(priv.Primes[0], bigOne)
- priv.Precomputed.Dp.Mod(priv.D, priv.Precomputed.Dp)
+ precomputed.fips = k
+ _, _, _, _, _, dP, dQ, qInv := k.Export()
+ precomputed.Dp = new(big.Int).SetBytes(dP)
+ precomputed.Dq = new(big.Int).SetBytes(dQ)
+ precomputed.Qinv = new(big.Int).SetBytes(qInv)
+ precomputed.CRTValues = make([]CRTValue, 0)
+ return precomputed, nil
+}
- priv.Precomputed.Dq = new(big.Int).Sub(priv.Primes[1], bigOne)
- priv.Precomputed.Dq.Mod(priv.D, priv.Precomputed.Dq)
+func (priv *PrivateKey) precomputeLegacy() (PrecomputedValues, error) {
+ var precomputed PrecomputedValues
- priv.Precomputed.Qinv = new(big.Int).ModInverse(priv.Primes[1], priv.Primes[0])
+ k, err := rsa.NewPrivateKeyWithoutCRT(priv.N.Bytes(), priv.E, priv.D.Bytes())
+ if err != nil {
+ return precomputed, err
+ }
+ precomputed.fips = k
+
+ if len(priv.Primes) < 2 {
+ return precomputed, nil
+ }
+
+ // Ensure the Mod and ModInverse calls below don't panic.
+ for _, prime := range priv.Primes {
+ if prime == nil {
+ return precomputed, errors.New("crypto/rsa: prime factor is nil")
+ }
+ if prime.Cmp(bigOne) <= 0 {
+ return precomputed, errors.New("crypto/rsa: prime factor is <= 1")
+ }
+ }
+
+ precomputed.Dp = new(big.Int).Sub(priv.Primes[0], bigOne)
+ precomputed.Dp.Mod(priv.D, precomputed.Dp)
+
+ precomputed.Dq = new(big.Int).Sub(priv.Primes[1], bigOne)
+ precomputed.Dq.Mod(priv.D, precomputed.Dq)
+
+ precomputed.Qinv = new(big.Int).ModInverse(priv.Primes[1], priv.Primes[0])
+ if precomputed.Qinv == nil {
+ return precomputed, errors.New("crypto/rsa: prime factors are not relatively prime")
+ }
r := new(big.Int).Mul(priv.Primes[0], priv.Primes[1])
- priv.Precomputed.CRTValues = make([]CRTValue, len(priv.Primes)-2)
+ precomputed.CRTValues = make([]CRTValue, len(priv.Primes)-2)
for i := 2; i < len(priv.Primes); i++ {
prime := priv.Primes[i]
- values := &priv.Precomputed.CRTValues[i-2]
+ values := &precomputed.CRTValues[i-2]
values.Exp = new(big.Int).Sub(prime, bigOne)
values.Exp.Mod(priv.D, values.Exp)
values.R = new(big.Int).Set(r)
values.Coeff = new(big.Int).ModInverse(r, prime)
+ if values.Coeff == nil {
+ return precomputed, errors.New("crypto/rsa: prime factors are not relatively prime")
+ }
r.Mul(r, prime)
}
- // Errors are discarded because we don't have a way to report them.
- // Anything that relies on Precomputed.fips will need to check for nil.
- if len(priv.Primes) == 2 {
- priv.Precomputed.fips, _ = rsa.NewPrivateKey(
- priv.N.Bytes(), priv.E, priv.D.Bytes(),
- priv.Primes[0].Bytes(), priv.Primes[1].Bytes(),
- priv.Precomputed.Dp.Bytes(), priv.Precomputed.Dq.Bytes(),
- priv.Precomputed.Qinv.Bytes())
- } else {
- priv.Precomputed.fips, _ = rsa.NewPrivateKeyWithoutCRT(
- priv.N.Bytes(), priv.E, priv.D.Bytes())
- }
+ return precomputed, nil
}
func fipsPublicKey(pub *PublicKey) (*rsa.PublicKey, error) {
if priv.Precomputed.fips != nil {
return priv.Precomputed.fips, nil
}
- // Make a copy of the private key to avoid modifying the original.
- k := *priv
- k.Precompute()
- if k.Precomputed.fips == nil {
- return nil, errors.New("crypto/rsa: invalid private key")
+ precomputed, err := priv.precompute()
+ if err != nil {
+ return nil, err
}
- return k.Precomputed.fips, nil
+ return precomputed.fips, nil
}