cryptoballot /
rsablind
| 1 | // All variables and functions in this file are carbon copy-paste from the standard library crypto/rsa |
||
| 2 | |||
| 3 | package rsablind |
||
| 4 | |||
| 5 | import ( |
||
| 6 | "crypto/rand" |
||
| 7 | "crypto/rsa" |
||
| 8 | "errors" |
||
| 9 | "io" |
||
| 10 | "math/big" |
||
| 11 | ) |
||
| 12 | |||
| 13 | var bigZero = big.NewInt(0) |
||
| 14 | var bigOne = big.NewInt(1) |
||
| 15 | |||
| 16 | // Carbon copy of crypto/rsa encrypt() |
||
| 17 | func encrypt(c *big.Int, pub *rsa.PublicKey, m *big.Int) *big.Int { |
||
| 18 | e := big.NewInt(int64(pub.E)) |
||
| 19 | c.Exp(m, e, pub.N) |
||
| 20 | return c |
||
| 21 | } |
||
| 22 | |||
| 23 | // Carbon copy of crypto/rsa decrypt() |
||
| 24 | // decrypt performs an RSA decryption, resulting in a plaintext integer. If a |
||
| 25 | // random source is given, RSA blinding is used. |
||
| 26 | func decrypt(random io.Reader, priv *rsa.PrivateKey, c *big.Int) (m *big.Int, err error) { |
||
|
0 ignored issues
–
show
introduced
by
Loading history...
|
|||
| 27 | // TODO(agl): can we get away with reusing blinds? |
||
| 28 | if c.Cmp(priv.N) > 0 { |
||
| 29 | err = rsa.ErrDecryption |
||
| 30 | return |
||
| 31 | } |
||
| 32 | |||
| 33 | var ir *big.Int |
||
| 34 | if random != nil { |
||
| 35 | // Blinding enabled. Blinding involves multiplying c by r^e. |
||
| 36 | // Then the decryption operation performs (m^e * r^e)^d mod n |
||
| 37 | // which equals mr mod n. The factor of r can then be removed |
||
| 38 | // by multiplying by the multiplicative inverse of r. |
||
| 39 | |||
| 40 | var r *big.Int |
||
| 41 | |||
| 42 | for { |
||
| 43 | r, err = rand.Int(random, priv.N) |
||
| 44 | if err != nil { |
||
| 45 | return |
||
| 46 | } |
||
| 47 | if r.Cmp(bigZero) == 0 { |
||
| 48 | r = bigOne |
||
| 49 | } |
||
| 50 | var ok bool |
||
| 51 | ir, ok = modInverse(r, priv.N) |
||
| 52 | if ok { |
||
| 53 | break |
||
| 54 | } |
||
| 55 | } |
||
| 56 | bigE := big.NewInt(int64(priv.E)) |
||
| 57 | rpowe := new(big.Int).Exp(r, bigE, priv.N) |
||
| 58 | cCopy := new(big.Int).Set(c) |
||
| 59 | cCopy.Mul(cCopy, rpowe) |
||
| 60 | cCopy.Mod(cCopy, priv.N) |
||
| 61 | c = cCopy |
||
| 62 | } |
||
| 63 | |||
| 64 | if priv.Precomputed.Dp == nil { |
||
| 65 | m = new(big.Int).Exp(c, priv.D, priv.N) |
||
| 66 | } else { |
||
| 67 | // We have the precalculated values needed for the CRT. |
||
| 68 | m = new(big.Int).Exp(c, priv.Precomputed.Dp, priv.Primes[0]) |
||
| 69 | m2 := new(big.Int).Exp(c, priv.Precomputed.Dq, priv.Primes[1]) |
||
| 70 | m.Sub(m, m2) |
||
| 71 | if m.Sign() < 0 { |
||
| 72 | m.Add(m, priv.Primes[0]) |
||
| 73 | } |
||
| 74 | m.Mul(m, priv.Precomputed.Qinv) |
||
| 75 | m.Mod(m, priv.Primes[0]) |
||
| 76 | m.Mul(m, priv.Primes[1]) |
||
| 77 | m.Add(m, m2) |
||
| 78 | |||
| 79 | for i, values := range priv.Precomputed.CRTValues { |
||
| 80 | prime := priv.Primes[2+i] |
||
| 81 | m2.Exp(c, values.Exp, prime) |
||
| 82 | m2.Sub(m2, m) |
||
| 83 | m2.Mul(m2, values.Coeff) |
||
| 84 | m2.Mod(m2, prime) |
||
| 85 | if m2.Sign() < 0 { |
||
| 86 | m2.Add(m2, prime) |
||
| 87 | } |
||
| 88 | m2.Mul(m2, values.R) |
||
| 89 | m.Add(m, m2) |
||
| 90 | } |
||
| 91 | } |
||
| 92 | |||
| 93 | if ir != nil { |
||
| 94 | // Unblind. |
||
| 95 | m.Mul(m, ir) |
||
| 96 | m.Mod(m, priv.N) |
||
| 97 | } |
||
| 98 | |||
| 99 | return |
||
| 100 | } |
||
| 101 | |||
| 102 | // Carbon-copy of crypto/rsa decryptAndCheck() |
||
| 103 | func decryptAndCheck(random io.Reader, priv *rsa.PrivateKey, c *big.Int) (m *big.Int, err error) { |
||
| 104 | m, err = decrypt(random, priv, c) |
||
| 105 | if err != nil { |
||
| 106 | return nil, err |
||
| 107 | } |
||
| 108 | |||
| 109 | // In order to defend against errors in the CRT computation, m^e is |
||
| 110 | // calculated, which should match the original ciphertext. |
||
| 111 | check := encrypt(new(big.Int), &priv.PublicKey, m) |
||
| 112 | if c.Cmp(check) != 0 { |
||
| 113 | return nil, errors.New("rsa: internal error") |
||
| 114 | } |
||
| 115 | return m, nil |
||
| 116 | } |
||
| 117 | |||
| 118 | // Carbon-copy of crypto/rsa modInverse() |
||
| 119 | // modInverse returns ia, the inverse of a in the multiplicative group of prime |
||
| 120 | // order n. It requires that a be a member of the group (i.e. less than n). |
||
| 121 | func modInverse(a, n *big.Int) (ia *big.Int, ok bool) { |
||
| 122 | g := new(big.Int) |
||
| 123 | x := new(big.Int) |
||
| 124 | y := new(big.Int) |
||
| 125 | g.GCD(x, y, a, n) |
||
| 126 | if g.Cmp(bigOne) != 0 { |
||
| 127 | // In this case, a and n aren't coprime and we cannot calculate |
||
| 128 | // the inverse. This happens because the values of n are nearly |
||
| 129 | // prime (being the product of two primes) rather than truly |
||
| 130 | // prime. |
||
| 131 | return |
||
| 132 | } |
||
| 133 | |||
| 134 | if x.Cmp(bigOne) < 0 { |
||
| 135 | // 0 is not the multiplicative inverse of any element so, if x |
||
| 136 | // < 1, then x is negative. |
||
| 137 | x.Add(x, n) |
||
| 138 | } |
||
| 139 | |||
| 140 | return x, true |
||
| 141 | } |
||
| 142 |