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
introduced
by
![]() |
|||
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 |