// randomNumber returns a uniform random value in [0, max). func randomNumber(rand io.Reader, max *big.Int) (n *big.Int, err os.Error) { k := (max.Len() + 7) / 8 // r is the number of bits in the used in the most significant byte of // max. r := uint(max.Len() % 8) if r == 0 { r = 8 } bytes := make([]byte, k) n = new(big.Int) for { _, err = io.ReadFull(rand, bytes) if err != nil { return } // Clear bits in the first byte to increase the probability // that the candidate is < max. bytes[0] &= uint8(int(1<<r) - 1) n.SetBytes(bytes) if big.CmpInt(n, max) < 0 { return } } return }
// 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) { g := new(big.Int) x := new(big.Int) y := new(big.Int) big.GcdInt(g, x, y, a, n) if big.CmpInt(x, 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 }
// decrypt performs an RSA decryption, resulting in a plaintext integer. If a // random source is given, RSA blinding is used. func decrypt(rand io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int, err os.Error) { // TODO(agl): can we get away with reusing blinds? if big.CmpInt(c, priv.N) > 0 { err = DecryptionError{} return } var ir *big.Int if rand != nil { // Blinding enabled. Blinding involves multiplying c by r^e. // Then the decryption operation performs (m^e * r^e)^d mod n // which equals mr mod n. The factor of r can then be removed // by multipling by the multiplicative inverse of r. r, err1 := randomNumber(rand, priv.N) if err1 != nil { err = err1 return } if big.CmpInt(r, bigZero) == 0 { r = bigOne } ir = modInverse(r, priv.N) bigE := big.NewInt(int64(priv.E)) rpowe := new(big.Int).Exp(r, bigE, priv.N) c.Mul(c, rpowe) c.Mod(c, priv.N) } m = new(big.Int).Exp(c, priv.D, priv.N) if ir != nil { // Unblind. m.Mul(m, ir) m.Mod(m, priv.N) } return }
func (priv PrivateKey) Validate() os.Error { /* TODO(agl): Enable once big implements ProbablyPrime. // Check that p and q are prime. if !priv.P.ProbablyPrime(20) { return os.ErrorString("P is composite"); } if !priv.Q.ProbablyPrime(20) { return os.ErrorString("Q is composite"); } */ // Check that p*q == n. modulus := new(big.Int).Mul(priv.P, priv.Q) if big.CmpInt(modulus, priv.N) != 0 { return os.ErrorString("invalid modulus") } // Check that e and totient(p, q) are coprime. pminus1 := new(big.Int).Sub(priv.P, bigOne) qminus1 := new(big.Int).Sub(priv.Q, bigOne) totient := new(big.Int).Mul(pminus1, qminus1) 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 big.CmpInt(gcd, bigOne) != 0 { return os.ErrorString("invalid public exponent E") } // Check that de ≡ 1 (mod totient(p, q)) de := new(big.Int).Mul(priv.D, e) de.Mod(de, totient) if big.CmpInt(de, bigOne) != 0 { return os.ErrorString("invalid private exponent D") } return nil }