go-blindsecp256k1/blindsecp256k1.go
blindsecp256k1.goRaw
1// Package blindsecp256k1 implements the Blind signature scheme explained at
2// http://www.isecure-journal.com/article_39171_47f9ec605dd3918c2793565ec21fcd7a.pdf
3//
4// LICENSE can be found at https://github.com/arnaucube/go-blindsecp256k1/blob/master/LICENSE
5package blindsecp256k1
6
7// WARNING: WIP code
8
9import (
10 "bytes"
11 "crypto/rand"
12 "math/big"
13
14 "github.com/ethereum/go-ethereum/crypto/secp256k1"
15)
16
17type Point struct {
18 X *big.Int
19 Y *big.Int
20}
21
22var (
23 G *Point = &Point{
24 X: secp256k1.S256().Gx,
25 Y: secp256k1.S256().Gy,
26 }
27
28 N *big.Int = secp256k1.S256().N
29)
30
31func (p *Point) Add(q *Point) *Point {
32 x, y := secp256k1.S256().Add(p.X, p.Y, q.X, q.Y)
33 return &Point{
34 X: x,
35 Y: y,
36 }
37}
38
39func (p *Point) Mul(scalar *big.Int) *Point {
40 x, y := secp256k1.S256().ScalarMult(p.X, p.Y, scalar.Bytes())
41 return &Point{
42 X: x,
43 Y: y,
44 }
45}
46
47func newRand() *big.Int {
48 var b [32]byte
49 _, err := rand.Read(b[:])
50 if err != nil {
51 panic(err)
52 }
53 bi := new(big.Int).SetBytes(b[:])
54 return new(big.Int).Mod(bi, N)
55}
56
57type PrivateKey big.Int
58type PublicKey Point
59
60func NewPrivateKey() *PrivateKey {
61 k := newRand()
62 sk := PrivateKey(*k)
63 return &sk
64}
65
66func (sk *PrivateKey) BigInt() *big.Int {
67 return (*big.Int)(sk)
68}
69
70func (sk *PrivateKey) Public() *PublicKey {
71 Q := G.Mul(sk.BigInt())
72 pk := PublicKey(*Q)
73 return &pk
74}
75
76func (pk *PublicKey) Point() *Point {
77 return (*Point)(pk)
78}
79
80type SignerPrivateData struct {
81 d *PrivateKey
82 k *big.Int
83}
84type SignerPublicData struct {
85 // Q is the Signer Public Key
86 Q *PublicKey // = skG
87 R *Point // = kG
88}
89
90func NewSigner() *SignerPrivateData {
91 sk := NewPrivateKey()
92 k := newRand()
93 return &SignerPrivateData{
94 d: sk,
95 k: k,
96 }
97}
98
99func (signer *SignerPrivateData) PublicData() *SignerPublicData {
100 return &SignerPublicData{
101 Q: signer.d.Public(), // Q = dG
102 R: G.Mul(signer.k), // R = kG
103 }
104}
105
106func (signer *SignerPrivateData) BlindSign(mBlinded *big.Int) *big.Int {
107 // TODO add pending checks
108 // s' = d(m') + k
109 sBlind := new(big.Int).Add(
110 new(big.Int).Mul(signer.d.BigInt(), mBlinded),
111 signer.k)
112 return sBlind
113}
114
115type UserSecretData struct {
116 a *big.Int
117 b *big.Int
118 c *big.Int
119
120 F *Point // public
121}
122
123func Blind(m *big.Int, signer *SignerPublicData) (*big.Int, *UserSecretData) {
124 u := &UserSecretData{}
125 u.a = newRand()
126 u.b = newRand()
127 u.c = newRand()
128 binv := new(big.Int).ModInverse(u.b, N)
129
130 // F = b^-1 R + a b^-1 Q + c G
131 bR := signer.R.Mul(binv)
132 abinv := new(big.Int).Mul(u.a, binv)
133 abinv = new(big.Int).Mod(abinv, N)
134 abQ := signer.Q.Point().Mul(abinv)
135 cG := G.Mul(u.c)
136 u.F = bR.Add(abQ).Add(cG)
137 // TODO check F==O
138
139 r := new(big.Int).Mod(u.F.X, N)
140
141 // m' = br(m)+a
142 br := new(big.Int).Mul(u.b, r)
143 brm := new(big.Int).Mul(br, m)
144 mBlinded := new(big.Int).Add(brm, u.a)
145 mBlinded = new(big.Int).Mod(mBlinded, N)
146 return mBlinded, u
147}
148
149type Signature struct {
150 S *big.Int
151 F *Point
152}
153
154func Unblind(sBlind, m *big.Int, u *UserSecretData) *Signature {
155 // s = b^-1 s' + c
156 binv := new(big.Int).ModInverse(u.b, N)
157 bs := new(big.Int).Mul(binv, sBlind)
158 s := new(big.Int).Add(bs, u.c)
159 s = new(big.Int).Mod(s, N)
160
161 return &Signature{
162 S: s,
163 F: u.F,
164 }
165}
166
167func Verify(m *big.Int, signature *Signature, q *PublicKey) bool {
168 // TODO add pending checks
169 sG := G.Mul(signature.S) // sG
170
171 r := new(big.Int).Mod(signature.F.X, N) // r = Fx mod N
172 rm := new(big.Int).Mul(r, m)
173 rm = new(big.Int).Mod(rm, N)
174 rmQ := q.Point().Mul(rm)
175 rmQF := rmQ.Add(signature.F) // rmQ + F
176
177 // check sG == rmQ + F
178 if bytes.Equal(sG.X.Bytes(), rmQF.X.Bytes()) &&
179 bytes.Equal(sG.Y.Bytes(), rmQF.Y.Bytes()) {
180 return true
181 }
182 return false
183}