Completed
Push — master ( a90616...aaa45d )
by Patrick D
01:33
created

rsablind.go (6 issues)

Severity
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
comment on exported function Blind should be of the form "Blind ..."
Loading history...
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
comment on exported function BlindSign should be of the form "BlindSign ..."
Loading history...
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
comment on exported function Unblind should be of the form "Unblind ..."
Loading history...
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
comment on exported function VerifyBlindSignature should be of the form "VerifyBlindSignature ..."
Loading history...
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
if block ends with a return statement, so drop this else and outdent its block
Loading history...
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
cyclomatic complexity 12 of function decrypt() is high (> 10)
Loading history...
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