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