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
5//
6package blindsecp256k1
7
8// WARNING: WIP code
9
10import (
11 "bytes"
12 "crypto/rand"
13 "math/big"
14
15 "github.com/btcsuite/btcd/btcec"
16)
17
18var (
19 // G represents the base point of secp256k1
20 G *Point = &Point{
21 X: btcec.S256().Gx,
22 Y: btcec.S256().Gy,
23 }
24
25 // N represents the order of G of secp256k1
26 N *big.Int = btcec.S256().N
27)
28
29// Point represents a point on the secp256k1 curve
30type Point struct {
31 X *big.Int
32 Y *big.Int
33}
34
35// Add performs the Point addition
36func (p *Point) Add(q *Point) *Point {
37 x, y := btcec.S256().Add(p.X, p.Y, q.X, q.Y)
38 return &Point{
39 X: x,
40 Y: y,
41 }
42}
43
44// Mul performs the Point scalar multiplication
45func (p *Point) Mul(scalar *big.Int) *Point {
46 x, y := btcec.S256().ScalarMult(p.X, p.Y, scalar.Bytes())
47 return &Point{
48 X: x,
49 Y: y,
50 }
51}
52
53// WIP
54func newRand() *big.Int {
55 var b [32]byte
56 _, err := rand.Read(b[:])
57 if err != nil {
58 panic(err)
59 }
60 bi := new(big.Int).SetBytes(b[:])
61 return new(big.Int).Mod(bi, N)
62}
63
64// PrivateKey represents the signer's private key
65type PrivateKey big.Int
66
67// PublicKey represents the signer's public key
68type PublicKey Point
69
70// NewPrivateKey returns a new random private key
71func NewPrivateKey() *PrivateKey {
72 k := newRand()
73 sk := PrivateKey(*k)
74 return &sk
75}
76
77// BigInt returns a *big.Int representation of the PrivateKey
78func (sk *PrivateKey) BigInt() *big.Int {
79 return (*big.Int)(sk)
80}
81
82// Public returns the PublicKey from the PrivateKey
83func (sk *PrivateKey) Public() *PublicKey {
84 Q := G.Mul(sk.BigInt())
85 pk := PublicKey(*Q)
86 return &pk
87}
88
89// Point returns a *Point representation of the PublicKey
90func (pk *PublicKey) Point() *Point {
91 return (*Point)(pk)
92}
93
94// SignerPrivateData contains the secret values from the Signer
95type SignerPrivateData struct {
96 D *PrivateKey
97 K *big.Int
98}
99
100// SignerPublicData contains the public values from the Signer (generated from
101// its SignerPrivateData)
102type SignerPublicData struct {
103 // Q is the Signer Public Key
104 Q *PublicKey // = skG
105 R *Point // = kG
106}
107
108// NewSigner returns a new SignerPrivateData with random D & K
109func NewSigner() *SignerPrivateData {
110 sk := NewPrivateKey()
111 k := newRand()
112 return &SignerPrivateData{
113 D: sk,
114 K: k,
115 }
116}
117
118// PublicData returns the SignerPublicData from the SignerPrivateData
119func (signer *SignerPrivateData) PublicData() *SignerPublicData {
120 return &SignerPublicData{
121 Q: signer.D.Public(), // Q = dG
122 R: G.Mul(signer.K), // R = kG
123 }
124}
125
126// BlindSign performs the blind signature on the given mBlinded using
127// SignerPrivateData values
128func (signer *SignerPrivateData) BlindSign(mBlinded *big.Int) *big.Int {
129 // TODO add pending checks
130 // s' = d(m') + k
131 sBlind := new(big.Int).Add(
132 new(big.Int).Mul(signer.D.BigInt(), mBlinded),
133 signer.K)
134 return sBlind
135}
136
137// UserSecretData contains the secret values from the User (a, b, c) and the
138// public F
139type UserSecretData struct {
140 A *big.Int
141 B *big.Int
142 C *big.Int
143
144 F *Point // public
145}
146
147// Blind performs the blinding operation on m using SignerPublicData parameters
148func Blind(m *big.Int, signer *SignerPublicData) (*big.Int, *UserSecretData) {
149 u := &UserSecretData{}
150 u.A = newRand()
151 u.B = newRand()
152 u.C = newRand()
153 binv := new(big.Int).ModInverse(u.B, N)
154
155 // F = b^-1 R + a b^-1 Q + c G
156 bR := signer.R.Mul(binv)
157 abinv := new(big.Int).Mul(u.A, binv)
158 abinv = new(big.Int).Mod(abinv, N)
159 abQ := signer.Q.Point().Mul(abinv)
160 cG := G.Mul(u.C)
161 u.F = bR.Add(abQ).Add(cG)
162 // TODO check F==O
163
164 r := new(big.Int).Mod(u.F.X, N)
165
166 // m' = br(m)+a
167 br := new(big.Int).Mul(u.B, r)
168 brm := new(big.Int).Mul(br, m)
169 mBlinded := new(big.Int).Add(brm, u.A)
170 mBlinded = new(big.Int).Mod(mBlinded, N)
171 return mBlinded, u
172}
173
174// Signature contains the signature values S & F
175type Signature struct {
176 S *big.Int
177 F *Point
178}
179
180// Unblind performs the unblinding operation of the blinded signature for the
181// given message m and the UserSecretData
182func Unblind(sBlind, m *big.Int, u *UserSecretData) *Signature {
183 // s = b^-1 s' + c
184 binv := new(big.Int).ModInverse(u.B, N)
185 bs := new(big.Int).Mul(binv, sBlind)
186 s := new(big.Int).Add(bs, u.C)
187 s = new(big.Int).Mod(s, N)
188
189 return &Signature{
190 S: s,
191 F: u.F,
192 }
193}
194
195// Verify checks the signature of the message m for the given PublicKey
196func Verify(m *big.Int, signature *Signature, q *PublicKey) bool {
197 // TODO add pending checks
198 sG := G.Mul(signature.S) // sG
199
200 r := new(big.Int).Mod(signature.F.X, N) // r = Fx mod N
201 rm := new(big.Int).Mul(r, m)
202 rm = new(big.Int).Mod(rm, N)
203 rmQ := q.Point().Mul(rm)
204 rmQF := rmQ.Add(signature.F) // rmQ + F
205
206 // check sG == rmQ + F
207 if bytes.Equal(sG.X.Bytes(), rmQF.X.Bytes()) &&
208 bytes.Equal(sG.Y.Bytes(), rmQF.Y.Bytes()) {
209 return true
210 }
211 return false
212}