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