Issues (2)

rsablind.go (1 issue)

Severity
1
package rsablind
2
3
import (
4
	"crypto/rand"
5
	"crypto/rsa"
6
	"crypto/subtle"
7
	"io"
8
	"math/big"
9
)
10
11
// Blind blinds the hashes message.
12
//
13
// Given the Public Key of the signing entity and a hashed message, blind the message so it cannot be inspected by the signing entity.
14
//
15
// Use the Full-Domain-Hash package (https://github.com/cryptoballot/fdh) to expand the size of your hash to a secure size. You should
16
// use a full-domain-hash size of at least 1024 bits, but bigger is better. However, this hash size needs to remain significantly
17
// 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,
18
// or 4096 bit keys and 3072 bit hashes (hash size is 3/4 the key size).
19
//
20
// This function returns the blinded message and an unblinding factor that can be used in conjunction with the `Unblind()` function to
21
// unblind the signature after the message has been signed.
22
func Blind(key *rsa.PublicKey, hashed []byte) (blindedData []byte, unblinder []byte, err error) {
23
	bitlen := key.N.BitLen()
24
	if len(hashed)*8 > bitlen {
25
		return nil, nil, rsa.ErrMessageTooLong
26
	}
27
28
	blinded, unblinderBig, err := blind(rand.Reader, key, new(big.Int).SetBytes(hashed))
29
	if err != nil {
30
		return nil, nil, err
31
	}
32
33
	return blinded.Bytes(), unblinderBig.Bytes(), nil
34
}
35
36
// BlindSign signs the provided hashed message blindly.
37
//
38
// The private key used here should not be used for any other purpose other than blind signing (use for other purposes is insecure
39
// when also using it for blind signatures)
40
func BlindSign(key *rsa.PrivateKey, hashed []byte) ([]byte, error) {
41
	bitlen := key.PublicKey.N.BitLen()
42
	if len(hashed)*8 > bitlen {
43
		return nil, rsa.ErrMessageTooLong
44
	}
45
46
	c := new(big.Int).SetBytes(hashed)
47
	m, err := decryptAndCheck(rand.Reader, key, c)
48
	if err != nil {
49
		return nil, err
50
	}
51
52
	return m.Bytes(), nil
53
}
54
55
// Unblind unblinds the blind signature.
56
//
57
// Given the Public Key of the signing entity, the blind signature, and the unblinding factor (obtained from `Blind()`), recover a new
58
// signature that will validate against the original hashed message.
59
func Unblind(pub *rsa.PublicKey, blindedSig, unblinder []byte) []byte {
60
	m := new(big.Int).SetBytes(blindedSig)
61
	unblinderBig := new(big.Int).SetBytes(unblinder)
62
	m.Mul(m, unblinderBig)
63
	m.Mod(m, pub.N)
64
	return m.Bytes()
65
}
66
67
// VerifyBlindSignature verifies an unblinded blind signature.
68
//
69
// Verify that the unblinded signature properly signs the non-blinded (original) hashed message
70
func VerifyBlindSignature(pub *rsa.PublicKey, hashed, sig []byte) error {
71
	m := new(big.Int).SetBytes(hashed)
72
	bigSig := new(big.Int).SetBytes(sig)
73
74
	c := encrypt(new(big.Int), pub, bigSig)
75
76
	if subtle.ConstantTimeCompare(m.Bytes(), c.Bytes()) == 1 {
77
		return nil
78
	} else {
0 ignored issues
show
if block ends with a return statement, so drop this else and outdent its block
Loading history...
79
		return rsa.ErrVerification
80
	}
81
}
82
83
// Adapted from from crypto/rsa decrypt
84
func blind(random io.Reader, key *rsa.PublicKey, c *big.Int) (blinded, unblinder *big.Int, err error) {
85
	// Blinding enabled. Blinding involves multiplying c by r^e.
86
	// Then the decryption operation performs (m^e * r^e)^d mod n
87
	// which equals mr mod n. The factor of r can then be removed
88
	// by multiplying by the multiplicative inverse of r.
89
90
	var r *big.Int
91
92
	for {
93
		r, err = rand.Int(random, key.N)
94
		if err != nil {
95
			return
96
		}
97
		if r.Cmp(bigZero) == 0 {
98
			r = bigOne
99
		}
100
		ir, ok := modInverse(r, key.N)
101
102
		if ok {
103
			bigE := big.NewInt(int64(key.E))
104
			rpowe := new(big.Int).Exp(r, bigE, key.N)
105
			cCopy := new(big.Int).Set(c)
106
			cCopy.Mul(cCopy, rpowe)
107
			cCopy.Mod(cCopy, key.N)
108
			return cCopy, ir, nil
109
		}
110
	}
111
}
112