Beispiel #1
0
// GenerateMultiPrimeKey generates a multi-prime RSA keypair of the given bit
// size, as suggested in [1]. Although the public keys are compatible
// (actually, indistinguishable) from the 2-prime case, the private keys are
// not. Thus it may not be possible to export multi-prime private keys in
// certain formats or to subsequently import them into other code.
//
// Table 1 in [2] suggests maximum numbers of primes for a given size.
//
// [1] US patent 4405829 (1972, expired)
// [2] http://www.cacr.math.uwaterloo.ca/techreports/2006/cacr2006-16.pdf
func GenerateMultiPrimeKey(random io.Reader, nprimes int, bits int) (priv *PrivateKey, err error) {
	priv = new(PrivateKey)
	priv.E = 65537

	if nprimes < 2 {
		return nil, errors.New("rsa.GenerateMultiPrimeKey: nprimes must be >= 2")
	}

	primes := make([]*big.Int, nprimes)

NextSetOfPrimes:
	for {
		todo := bits
		for i := 0; i < nprimes; i++ {
			primes[i], err = rand.Prime(random, todo/(nprimes-i))
			if err != nil {
				return nil, err
			}
			todo -= primes[i].BitLen()
		}

		// Make sure that primes is pairwise unequal.
		for i, prime := range primes {
			for j := 0; j < i; j++ {
				if prime.Cmp(primes[j]) == 0 {
					continue NextSetOfPrimes
				}
			}
		}

		n := new(big.Int).Set(bigOne)
		totient := new(big.Int).Set(bigOne)
		pminus1 := new(big.Int)
		for _, prime := range primes {
			n.Mul(n, prime)
			pminus1.Sub(prime, bigOne)
			totient.Mul(totient, pminus1)
		}

		g := new(big.Int)
		priv.D = new(big.Int)
		y := new(big.Int)
		e := big.NewInt(int64(priv.E))
		big.GcdInt(g, priv.D, y, e, totient)

		if g.Cmp(bigOne) == 0 {
			priv.D.Add(priv.D, totient)
			priv.Primes = primes
			priv.N = n

			break
		}
	}

	priv.Precompute()
	return
}
Beispiel #2
0
// Validate performs basic sanity checks on the key.
// It returns nil if the key is valid, or else an error describing a problem.
func (priv *PrivateKey) Validate() error {
	// Check that the prime factors are actually prime. Note that this is
	// just a sanity check. Since the random witnesses chosen by
	// ProbablyPrime are deterministic, given the candidate number, it's
	// easy for an attack to generate composites that pass this test.
	for _, prime := range priv.Primes {
		if !big.ProbablyPrime(prime, 20) {
			return errors.New("prime factor is composite")
		}
	}

	// Check that Πprimes == n.
	modulus := new(big.Int).Set(bigOne)
	for _, prime := range priv.Primes {
		modulus.Mul(modulus, prime)
	}
	if modulus.Cmp(priv.N) != 0 {
		return errors.New("invalid modulus")
	}
	// Check that e and totient(Πprimes) are coprime.
	totient := new(big.Int).Set(bigOne)
	for _, prime := range priv.Primes {
		pminus1 := new(big.Int).Sub(prime, bigOne)
		totient.Mul(totient, pminus1)
	}
	e := big.NewInt(int64(priv.E))
	gcd := new(big.Int)
	x := new(big.Int)
	y := new(big.Int)
	big.GcdInt(gcd, x, y, totient, e)
	if gcd.Cmp(bigOne) != 0 {
		return errors.New("invalid public exponent E")
	}
	// Check that de ≡ 1 (mod totient(Πprimes))
	de := new(big.Int).Mul(priv.D, e)
	de.Mod(de, totient)
	if de.Cmp(bigOne) != 0 {
		return errors.New("invalid private exponent D")
	}
	return nil
}
Beispiel #3
0
// modInverse returns ia, the inverse of a in the multiplicative group of prime
// order n. It requires that a be a member of the group (i.e. less than n).
func modInverse(a, n *big.Int) (ia *big.Int, ok bool) {
	g := new(big.Int)
	x := new(big.Int)
	y := new(big.Int)
	big.GcdInt(g, x, y, a, n)
	if g.Cmp(bigOne) != 0 {
		// In this case, a and n aren't coprime and we cannot calculate
		// the inverse. This happens because the values of n are nearly
		// prime (being the product of two primes) rather than truly
		// prime.
		return
	}

	if x.Cmp(bigOne) < 0 {
		// 0 is not the multiplicative inverse of any element so, if x
		// < 1, then x is negative.
		x.Add(x, n)
	}

	return x, true
}