arnaucube
arnaucube/go-blindsecp256k1Public Self-hosted repository
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}