1 | // Package rsablind implements a RSA Blind Signature Scheme. |
||
2 | // |
||
3 | // In cryptography, a blind signature is a form of digital signature in which the content of a message is disguised (blinded) before it is signed. The entity signing the message does not know the contents of the message being signed. |
||
4 | // |
||
5 | // Caveats |
||
6 | // |
||
7 | // 1. This library has not undergone a security review or audit and should not be used in production code. |
||
8 | // |
||
9 | // 2. The key used to sign the blinded messages should not be used for any other purpose. Re-using this key in other contexts opens it up to attack. |
||
10 | // |
||
11 | // 3. Use the Full-Domain-Hash package (https://github.com/cryptoballot/fdh) to expand the size of your hash to a secure size. You should use a full-domain-hash size of at least 1024 bits, but bigger is better. However, this hash size needs to remain significantly smaller than your key size to avoid RSA verification failures. A good rule of thumb is to use 2048 bit keys and 1536 bit hashes, or 4096 bit keys and 3072 bit hashes (hash size is 3/4 the key size). |
||
12 | // |
||
13 | // 4. Because we use a full-domain hash size that is less than the key size, this scheme is theoretically open to an Index Calculation Attack (see http://www.jscoron.fr/publications/isodcc.pdf). However, with a large enough RSA key (recommended 2048 bits or larger), and a large enough full-domain-hash (1024 bits or larger) this attack in infeasable. |
||
14 | package rsablind |
||
15 | |||
16 | import ( |
||
17 | "crypto/rand" |
||
18 | "crypto/rsa" |
||
19 | "crypto/subtle" |
||
20 | "errors" |
||
21 | "io" |
||
22 | "math/big" |
||
23 | ) |
||
24 | |||
25 | // Given the Public Key of the signing entity and a hashed message, blind the message so it cannot be inspected by the signing entity. |
||
0 ignored issues
–
show
introduced
by
![]() |
|||
26 | // |
||
27 | // Use the Full-Domain-Hash package (https://github.com/cryptoballot/fdh) to expand the size of your hash to a secure size. You should |
||
28 | // use a full-domain-hash size of at least 1024 bits, but bigger is better. However, this hash size needs to remain significantly |
||
29 | // smaller than your key size to avoid RSA verification failures. A good rule of thumb is to use 2048 bit keys and 1536 bit hashes, |
||
30 | // or 4096 bit keys and 3072 bit hashes (hash size is 3/4 the key size). |
||
31 | // |
||
32 | // This function returns the blinded message and an unblinding factor that can be used in conjuction with the `Unblind()` function to |
||
33 | // unblind the signature after the message has been signed. |
||
34 | func Blind(key *rsa.PublicKey, hashed []byte) (blindedData []byte, unblinder []byte, err error) { |
||
35 | bitlen := key.N.BitLen() |
||
36 | if len(hashed)*8 > bitlen { |
||
37 | return nil, nil, rsa.ErrMessageTooLong |
||
38 | } |
||
39 | |||
40 | blinded, unblinderBig, err := blind(rand.Reader, key, new(big.Int).SetBytes(hashed)) |
||
41 | if err != nil { |
||
42 | return nil, nil, err |
||
43 | } |
||
44 | |||
45 | return blinded.Bytes(), unblinderBig.Bytes(), nil |
||
46 | } |
||
47 | |||
48 | // Given a private key and a hashed message, blind sign the hashed message. |
||
0 ignored issues
–
show
|
|||
49 | // |
||
50 | // The private key used here should not be used for any other purpose other than blind signing (use for other purposes is insecure |
||
51 | // when also using it for blind signatures) |
||
52 | func BlindSign(key *rsa.PrivateKey, hashed []byte) ([]byte, error) { |
||
53 | bitlen := key.PublicKey.N.BitLen() |
||
54 | if len(hashed)*8 > bitlen { |
||
55 | return nil, rsa.ErrMessageTooLong |
||
56 | } |
||
57 | |||
58 | c := new(big.Int).SetBytes(hashed) |
||
59 | m, err := decryptAndCheck(rand.Reader, key, c) |
||
60 | if err != nil { |
||
61 | return nil, err |
||
62 | } |
||
63 | |||
64 | return m.Bytes(), nil |
||
65 | } |
||
66 | |||
67 | // Given the Public Key of the signing entity, the blind signature, and the unblinding factor (obtained from `Blind()`), recover a new |
||
0 ignored issues
–
show
|
|||
68 | // signature that will validate against the original hashed message. |
||
69 | func Unblind(pub *rsa.PublicKey, blindedSig, unblinder []byte) []byte { |
||
70 | m := new(big.Int).SetBytes(blindedSig) |
||
71 | unblinderBig := new(big.Int).SetBytes(unblinder) |
||
72 | m.Mul(m, unblinderBig) |
||
73 | m.Mod(m, pub.N) |
||
74 | return m.Bytes() |
||
75 | } |
||
76 | |||
77 | // Verify that the unblinded signature properly signs the non-blinded (original) hashed message |
||
0 ignored issues
–
show
|
|||
78 | func VerifyBlindSignature(pub *rsa.PublicKey, hashed, sig []byte) error { |
||
79 | m := new(big.Int).SetBytes(hashed) |
||
80 | bigSig := new(big.Int).SetBytes(sig) |
||
81 | |||
82 | c := encrypt(new(big.Int), pub, bigSig) |
||
83 | |||
84 | if subtle.ConstantTimeCompare(m.Bytes(), c.Bytes()) == 1 { |
||
85 | return nil |
||
86 | } else { |
||
0 ignored issues
–
show
|
|||
87 | return rsa.ErrVerification |
||
88 | } |
||
89 | } |
||
90 | |||
91 | // Adapted from from crypto/rsa decrypt |
||
92 | func blind(random io.Reader, key *rsa.PublicKey, c *big.Int) (blinded, unblinder *big.Int, err error) { |
||
93 | // Blinding enabled. Blinding involves multiplying c by r^e. |
||
94 | // Then the decryption operation performs (m^e * r^e)^d mod n |
||
95 | // which equals mr mod n. The factor of r can then be removed |
||
96 | // by multiplying by the multiplicative inverse of r. |
||
97 | |||
98 | var r *big.Int |
||
99 | |||
100 | for { |
||
101 | r, err = rand.Int(random, key.N) |
||
102 | if err != nil { |
||
103 | return |
||
104 | } |
||
105 | if r.Cmp(bigZero) == 0 { |
||
106 | r = bigOne |
||
107 | } |
||
108 | ir, ok := modInverse(r, key.N) |
||
109 | |||
110 | if ok { |
||
111 | bigE := big.NewInt(int64(key.E)) |
||
112 | rpowe := new(big.Int).Exp(r, bigE, key.N) |
||
113 | cCopy := new(big.Int).Set(c) |
||
114 | cCopy.Mul(cCopy, rpowe) |
||
115 | cCopy.Mod(cCopy, key.N) |
||
116 | return cCopy, ir, nil |
||
117 | } |
||
118 | } |
||
119 | } |
||
120 | |||
121 | // All variables and functions below are carbon copy-paste from the standard library crypto/rsa |
||
122 | |||
123 | var bigZero = big.NewInt(0) |
||
124 | var bigOne = big.NewInt(1) |
||
125 | |||
126 | // Carbon copy of crypto/rsa encrypt() |
||
127 | func encrypt(c *big.Int, pub *rsa.PublicKey, m *big.Int) *big.Int { |
||
128 | e := big.NewInt(int64(pub.E)) |
||
129 | c.Exp(m, e, pub.N) |
||
130 | return c |
||
131 | } |
||
132 | |||
133 | // Carbon copy of crypto/rsa decrypt() |
||
134 | // decrypt performs an RSA decryption, resulting in a plaintext integer. If a |
||
135 | // random source is given, RSA blinding is used. |
||
136 | func decrypt(random io.Reader, priv *rsa.PrivateKey, c *big.Int) (m *big.Int, err error) { |
||
0 ignored issues
–
show
|
|||
137 | // TODO(agl): can we get away with reusing blinds? |
||
138 | if c.Cmp(priv.N) > 0 { |
||
139 | err = rsa.ErrDecryption |
||
140 | return |
||
141 | } |
||
142 | |||
143 | var ir *big.Int |
||
144 | if random != nil { |
||
145 | // Blinding enabled. Blinding involves multiplying c by r^e. |
||
146 | // Then the decryption operation performs (m^e * r^e)^d mod n |
||
147 | // which equals mr mod n. The factor of r can then be removed |
||
148 | // by multiplying by the multiplicative inverse of r. |
||
149 | |||
150 | var r *big.Int |
||
151 | |||
152 | for { |
||
153 | r, err = rand.Int(random, priv.N) |
||
154 | if err != nil { |
||
155 | return |
||
156 | } |
||
157 | if r.Cmp(bigZero) == 0 { |
||
158 | r = bigOne |
||
159 | } |
||
160 | var ok bool |
||
161 | ir, ok = modInverse(r, priv.N) |
||
162 | if ok { |
||
163 | break |
||
164 | } |
||
165 | } |
||
166 | bigE := big.NewInt(int64(priv.E)) |
||
167 | rpowe := new(big.Int).Exp(r, bigE, priv.N) |
||
168 | cCopy := new(big.Int).Set(c) |
||
169 | cCopy.Mul(cCopy, rpowe) |
||
170 | cCopy.Mod(cCopy, priv.N) |
||
171 | c = cCopy |
||
172 | } |
||
173 | |||
174 | if priv.Precomputed.Dp == nil { |
||
175 | m = new(big.Int).Exp(c, priv.D, priv.N) |
||
176 | } else { |
||
177 | // We have the precalculated values needed for the CRT. |
||
178 | m = new(big.Int).Exp(c, priv.Precomputed.Dp, priv.Primes[0]) |
||
179 | m2 := new(big.Int).Exp(c, priv.Precomputed.Dq, priv.Primes[1]) |
||
180 | m.Sub(m, m2) |
||
181 | if m.Sign() < 0 { |
||
182 | m.Add(m, priv.Primes[0]) |
||
183 | } |
||
184 | m.Mul(m, priv.Precomputed.Qinv) |
||
185 | m.Mod(m, priv.Primes[0]) |
||
186 | m.Mul(m, priv.Primes[1]) |
||
187 | m.Add(m, m2) |
||
188 | |||
189 | for i, values := range priv.Precomputed.CRTValues { |
||
190 | prime := priv.Primes[2+i] |
||
191 | m2.Exp(c, values.Exp, prime) |
||
192 | m2.Sub(m2, m) |
||
193 | m2.Mul(m2, values.Coeff) |
||
194 | m2.Mod(m2, prime) |
||
195 | if m2.Sign() < 0 { |
||
196 | m2.Add(m2, prime) |
||
197 | } |
||
198 | m2.Mul(m2, values.R) |
||
199 | m.Add(m, m2) |
||
200 | } |
||
201 | } |
||
202 | |||
203 | if ir != nil { |
||
204 | // Unblind. |
||
205 | m.Mul(m, ir) |
||
206 | m.Mod(m, priv.N) |
||
207 | } |
||
208 | |||
209 | return |
||
210 | } |
||
211 | |||
212 | // Carbon-copy of crypto/rsa decryptAndCheck() |
||
213 | func decryptAndCheck(random io.Reader, priv *rsa.PrivateKey, c *big.Int) (m *big.Int, err error) { |
||
214 | m, err = decrypt(random, priv, c) |
||
215 | if err != nil { |
||
216 | return nil, err |
||
217 | } |
||
218 | |||
219 | // In order to defend against errors in the CRT computation, m^e is |
||
220 | // calculated, which should match the original ciphertext. |
||
221 | check := encrypt(new(big.Int), &priv.PublicKey, m) |
||
222 | if c.Cmp(check) != 0 { |
||
223 | return nil, errors.New("rsa: internal error") |
||
224 | } |
||
225 | return m, nil |
||
226 | } |
||
227 | |||
228 | // Carbon-copy of crypto/rsa modInverse() |
||
229 | // modInverse returns ia, the inverse of a in the multiplicative group of prime |
||
230 | // order n. It requires that a be a member of the group (i.e. less than n). |
||
231 | func modInverse(a, n *big.Int) (ia *big.Int, ok bool) { |
||
232 | g := new(big.Int) |
||
233 | x := new(big.Int) |
||
234 | y := new(big.Int) |
||
235 | g.GCD(x, y, a, n) |
||
236 | if g.Cmp(bigOne) != 0 { |
||
237 | // In this case, a and n aren't coprime and we cannot calculate |
||
238 | // the inverse. This happens because the values of n are nearly |
||
239 | // prime (being the product of two primes) rather than truly |
||
240 | // prime. |
||
241 | return |
||
242 | } |
||
243 | |||
244 | if x.Cmp(bigOne) < 0 { |
||
245 | // 0 is not the multiplicative inverse of any element so, if x |
||
246 | // < 1, then x is negative. |
||
247 | x.Add(x, n) |
||
248 | } |
||
249 | |||
250 | return x, true |
||
251 | } |
||
252 |