arnaucube
arnaucube/go-blindsecp256k1Public Self-hosted repository
go-blindsecp256k1/blindsecp256k1.go
blindsecp256k1.goRaw
  1// Package blindsecp256k1 implements the Blind signature scheme explained at
  2// "New Blind Signature Schemes Based on the (Elliptic Curve) Discrete
  3// Logarithm Problem", by Hamid Mala & Nafiseh Nezhadansari
  4// https://sci-hub.do/10.1109/ICCKE.2013.6682844
  5//
  6// LICENSE can be found at https://github.com/arnaucube/go-blindsecp256k1/blob/master/LICENSE
  7//
  8package blindsecp256k1
  9
 10// WARNING: WIP code
 11
 12import (
 13	"bytes"
 14	"crypto/rand"
 15	"encoding/json"
 16	"fmt"
 17	"math/big"
 18
 19	"github.com/btcsuite/btcd/btcec"
 20	"github.com/ethereum/go-ethereum/crypto"
 21)
 22
 23var (
 24	// G represents the base point of secp256k1
 25	G *Point = &Point{
 26		X: btcec.S256().Gx,
 27		Y: btcec.S256().Gy,
 28	}
 29
 30	// N represents the order of G of secp256k1
 31	N *big.Int = btcec.S256().N
 32)
 33
 34// Point represents a point on the secp256k1 curve
 35type Point struct {
 36	X *big.Int
 37	Y *big.Int
 38}
 39
 40// Add performs the Point addition
 41func (p *Point) Add(q *Point) *Point {
 42	x, y := btcec.S256().Add(p.X, p.Y, q.X, q.Y)
 43	return &Point{
 44		X: x,
 45		Y: y,
 46	}
 47}
 48
 49// Mul performs the Point scalar multiplication
 50func (p *Point) Mul(scalar *big.Int) *Point {
 51	x, y := btcec.S256().ScalarMult(p.X, p.Y, scalar.Bytes())
 52	return &Point{
 53		X: x,
 54		Y: y,
 55	}
 56}
 57
 58// MarshalJSON implements the json marshaler for the Point
 59func (p Point) MarshalJSON() ([]byte, error) {
 60	return json.Marshal(&struct {
 61		X string `json:"x"`
 62		Y string `json:"y"`
 63	}{
 64		X: p.X.String(),
 65		Y: p.Y.String(),
 66	})
 67}
 68
 69// UnmarshalJSON implements the json unmarshaler for the Point
 70func (p *Point) UnmarshalJSON(b []byte) error {
 71	aux := &struct {
 72		X string `json:"x"`
 73		Y string `json:"y"`
 74	}{}
 75	err := json.Unmarshal(b, &aux)
 76	if err != nil {
 77		return err
 78	}
 79	x, ok := new(big.Int).SetString(aux.X, 10)
 80	if !ok {
 81		return fmt.Errorf("Can not parse Point.X %s", aux.X)
 82	}
 83	y, ok := new(big.Int).SetString(aux.Y, 10)
 84	if !ok {
 85		return fmt.Errorf("Can not parse Point.Y %s", aux.Y)
 86	}
 87	p.X = x
 88	p.Y = y
 89	return nil
 90}
 91
 92// WIP
 93func newRand() *big.Int {
 94	var b [32]byte
 95	_, err := rand.Read(b[:])
 96	if err != nil {
 97		panic(err)
 98	}
 99	bi := new(big.Int).SetBytes(b[:])
100	return new(big.Int).Mod(bi, N)
101}
102
103// PrivateKey represents the signer's private key
104type PrivateKey big.Int
105
106// PublicKey represents the signer's public key
107type PublicKey Point
108
109// MarshalJSON implements the json marshaler for the PublicKey
110func (pk PublicKey) MarshalJSON() ([]byte, error) {
111	return json.Marshal(pk.Point())
112}
113
114// UnmarshalJSON implements the json unmarshaler for the PublicKey
115func (pk *PublicKey) UnmarshalJSON(b []byte) error {
116	var point *Point
117	err := json.Unmarshal(b, &point)
118	if err != nil {
119		return err
120	}
121	pk.X = point.X
122	pk.Y = point.Y
123	return nil
124}
125
126// NewPrivateKey returns a new random private key
127func NewPrivateKey() *PrivateKey {
128	k := newRand()
129	sk := PrivateKey(*k)
130	return &sk
131}
132
133// BigInt returns a *big.Int representation of the PrivateKey
134func (sk *PrivateKey) BigInt() *big.Int {
135	return (*big.Int)(sk)
136}
137
138// Public returns the PublicKey from the PrivateKey
139func (sk *PrivateKey) Public() *PublicKey {
140	Q := G.Mul(sk.BigInt())
141	pk := PublicKey(*Q)
142	return &pk
143}
144
145// Point returns a *Point representation of the PublicKey
146func (pk *PublicKey) Point() *Point {
147	return (*Point)(pk)
148}
149
150// NewRequestParameters returns a new random k (secret) & R (public) parameters
151func NewRequestParameters() (*big.Int, *Point) {
152	k := newRand()
153	return k, G.Mul(k) // R = kG
154}
155
156// BlindSign performs the blind signature on the given mBlinded using the
157// PrivateKey and the secret k values
158func (sk *PrivateKey) BlindSign(mBlinded *big.Int, k *big.Int) *big.Int {
159	// TODO add pending checks
160	// s' = dm' + k
161	sBlind := new(big.Int).Add(
162		new(big.Int).Mul(sk.BigInt(), mBlinded),
163		k)
164	return sBlind
165}
166
167// UserSecretData contains the secret values from the User (a, b, c) and the
168// public F
169type UserSecretData struct {
170	A *big.Int
171	B *big.Int
172
173	F *Point // public (in the paper is R)
174}
175
176// Blind performs the blinding operation on m using signerR parameter
177func Blind(m *big.Int, signerR *Point) (*big.Int, *UserSecretData) {
178	u := &UserSecretData{}
179	u.A = newRand()
180	u.B = newRand()
181
182	// (R) F = aR' + bG
183	aR := signerR.Mul(u.A)
184	bG := G.Mul(u.B)
185	u.F = aR.Add(bG)
186
187	// TODO check that F != O (point at infinity)
188
189	rx := new(big.Int).Mod(u.F.X, N)
190
191	// m' = a^-1 rx h(m)
192	ainv := new(big.Int).ModInverse(u.A, N)
193	ainvrx := new(big.Int).Mul(ainv, rx)
194	hBytes := crypto.Keccak256(m.Bytes())
195	h := new(big.Int).SetBytes(hBytes)
196	mBlinded := new(big.Int).Mul(ainvrx, h)
197
198	return mBlinded, u
199}
200
201// Signature contains the signature values S & F
202type Signature struct {
203	S *big.Int
204	F *Point
205}
206
207// MarshalJSON implements the json marshaler for the Signature
208func (sig Signature) MarshalJSON() ([]byte, error) {
209	return json.Marshal(&struct {
210		S string `json:"s"`
211		F struct {
212			X string `json:"x"`
213			Y string `json:"y"`
214		} `json:"f"`
215	}{
216		S: sig.S.String(),
217		F: struct {
218			X string `json:"x"`
219			Y string `json:"y"`
220		}{
221			X: sig.F.X.String(),
222			Y: sig.F.Y.String(),
223		},
224	})
225}
226
227// UnmarshalJSON implements the json unmarshaler for the Signature
228func (sig *Signature) UnmarshalJSON(b []byte) error {
229	aux := &struct {
230		S string `json:"s"`
231		F struct {
232			X string `json:"x"`
233			Y string `json:"y"`
234		} `json:"f"`
235	}{}
236	err := json.Unmarshal(b, &aux)
237	if err != nil {
238		return err
239	}
240
241	s, ok := new(big.Int).SetString(aux.S, 10)
242	if !ok {
243		return fmt.Errorf("Can not parse sig.S %s", aux.S)
244	}
245	sig.S = s
246
247	x, ok := new(big.Int).SetString(aux.F.X, 10)
248	if !ok {
249		return fmt.Errorf("Can not parse sig.F.X %s", aux.F.X)
250	}
251	y, ok := new(big.Int).SetString(aux.F.Y, 10)
252	if !ok {
253		return fmt.Errorf("Can not parse sig.F.Y %s", aux.F.Y)
254	}
255	sig.F = &Point{}
256	sig.F.X = x
257	sig.F.Y = y
258	return nil
259}
260
261// Unblind performs the unblinding operation of the blinded signature for the
262// given message m and the UserSecretData
263func Unblind(sBlind, m *big.Int, u *UserSecretData) *Signature {
264	// s = a s' + b
265	as := new(big.Int).Mul(u.A, sBlind)
266	s := new(big.Int).Add(as, u.B)
267
268	return &Signature{
269		S: s,
270		F: u.F,
271	}
272}
273
274// Verify checks the signature of the message m for the given PublicKey
275func Verify(m *big.Int, s *Signature, q *PublicKey) bool {
276	// TODO add pending checks
277
278	sG := G.Mul(s.S) // sG
279
280	hBytes := crypto.Keccak256(m.Bytes())
281	h := new(big.Int).SetBytes(hBytes)
282
283	rx := new(big.Int).Mod(s.F.X, N)
284	rxh := new(big.Int).Mul(rx, h)
285	// rxhG := G.Mul(rxh) // originally the paper uses G
286	rxhG := q.Point().Mul(rxh)
287
288	right := s.F.Add(rxhG)
289
290	// check sG == R + rx h(m) G (where R in this code is F)
291	if bytes.Equal(sG.X.Bytes(), right.X.Bytes()) &&
292		bytes.Equal(sG.Y.Bytes(), right.Y.Bytes()) {
293		return true
294	}
295	return false
296}