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// NewRequestParameters returns a new random k (secret) & R (public) parameters
 97func NewRequestParameters() (*big.Int, *Point) {
 98	k := newRand()
 99	return k, G.Mul(k) // R = kG
100}
101
102// BlindSign performs the blind signature on the given mBlinded using
103// SignerPrivateData values
104func (sk *PrivateKey) BlindSign(mBlinded *big.Int, k *big.Int) *big.Int {
105	// TODO add pending checks
106	// s' = d(m') + k
107	sBlind := new(big.Int).Add(
108		new(big.Int).Mul(sk.BigInt(), mBlinded),
109		k)
110	return sBlind
111}
112
113// UserSecretData contains the secret values from the User (a, b, c) and the
114// public F
115type UserSecretData struct {
116	A *big.Int
117	B *big.Int
118	C *big.Int
119
120	F *Point // public
121}
122
123// Blind performs the blinding operation on m using SignerPublicData parameters
124func Blind(m *big.Int, signerPubK *PublicKey, signerR *Point) (*big.Int, *UserSecretData) {
125	u := &UserSecretData{}
126	u.A = newRand()
127	u.B = newRand()
128	u.C = newRand()
129	binv := new(big.Int).ModInverse(u.B, N)
130
131	// F = b^-1 R + a b^-1 Q + c G
132	bR := signerR.Mul(binv)
133	abinv := new(big.Int).Mul(u.A, binv)
134	abinv = new(big.Int).Mod(abinv, N)
135	abQ := signerPubK.Point().Mul(abinv)
136	cG := G.Mul(u.C)
137	u.F = bR.Add(abQ).Add(cG)
138	// TODO check F==O
139
140	r := new(big.Int).Mod(u.F.X, N)
141
142	// m' = br(m)+a
143	br := new(big.Int).Mul(u.B, r)
144	brm := new(big.Int).Mul(br, m)
145	mBlinded := new(big.Int).Add(brm, u.A)
146	mBlinded = new(big.Int).Mod(mBlinded, N)
147	return mBlinded, u
148}
149
150// Signature contains the signature values S & F
151type Signature struct {
152	S *big.Int
153	F *Point
154}
155
156// Unblind performs the unblinding operation of the blinded signature for the
157// given message m and the UserSecretData
158func Unblind(sBlind, m *big.Int, u *UserSecretData) *Signature {
159	// s = b^-1 s' + c
160	binv := new(big.Int).ModInverse(u.B, N)
161	bs := new(big.Int).Mul(binv, sBlind)
162	s := new(big.Int).Add(bs, u.C)
163	s = new(big.Int).Mod(s, N)
164
165	return &Signature{
166		S: s,
167		F: u.F,
168	}
169}
170
171// Verify checks the signature of the message m for the given PublicKey
172func Verify(m *big.Int, signature *Signature, q *PublicKey) bool {
173	// TODO add pending checks
174	sG := G.Mul(signature.S) // sG
175
176	r := new(big.Int).Mod(signature.F.X, N) // r = Fx mod N
177	rm := new(big.Int).Mul(r, m)
178	rm = new(big.Int).Mod(rm, N)
179	rmQ := q.Point().Mul(rm)
180	rmQF := rmQ.Add(signature.F) // rmQ + F
181
182	// check sG == rmQ + F
183	if bytes.Equal(sG.X.Bytes(), rmQF.X.Bytes()) &&
184		bytes.Equal(sG.Y.Bytes(), rmQF.Y.Bytes()) {
185		return true
186	}
187	return false
188}