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/ecdsa"
 15	"crypto/rand"
 16	"math/big"
 17
 18	"github.com/arnaucube/go-blindsecp256k1"
 19	"github.com/ethereum/go-ethereum/crypto/secp256k1"
 20)
 21
 22// WIP
 23func newRand() (*big.Int, error) {
 24	pk, err := ecdsa.GenerateKey(secp256k1.S256(), rand.Reader)
 25	if err != nil {
 26		return nil, err
 27	}
 28	return pk.D, nil
 29}
 30
 31// PrivateKey represents the signer's private key
 32type PrivateKey big.Int
 33
 34// NewPrivateKey returns a new random private key
 35func NewPrivateKey() (*PrivateKey, error) {
 36	k, err := newRand()
 37	if err != nil {
 38		return nil, err
 39	}
 40	sk := PrivateKey(*k)
 41	return &sk, nil
 42}
 43
 44// BigInt returns a *big.Int representation of the PrivateKey
 45func (sk *PrivateKey) BigInt() *big.Int {
 46	return (*big.Int)(sk)
 47}
 48
 49// Public returns the PublicKey from the PrivateKey
 50func (sk *PrivateKey) Public() *blindsecp256k1.PublicKey {
 51	Q := blindsecp256k1.G.Mul(sk.BigInt())
 52	pk := blindsecp256k1.PublicKey(*Q)
 53	return &pk
 54}
 55
 56// NewRequestParameters returns a new random k (secret) & R (public) parameters
 57func NewRequestParameters() (*big.Int, *blindsecp256k1.Point, error) {
 58	k, err := newRand()
 59	if err != nil {
 60		return nil, nil, err
 61	}
 62	// k, R = kG
 63	return k, blindsecp256k1.G.Mul(k), nil
 64}
 65
 66// BlindSign performs the blind signature on the given mBlinded using
 67// SignerPrivateData values
 68func (sk *PrivateKey) BlindSign(mBlinded *big.Int, k *big.Int) *big.Int {
 69	// WARNING missing checks, this package is not updated, use
 70	// blindsecp256k1 instead
 71	// TODO add pending checks
 72	// s' = d(m') + k
 73	sBlind := new(big.Int).Add(
 74		new(big.Int).Mul(sk.BigInt(), mBlinded),
 75		k)
 76	return sBlind
 77}
 78
 79// UserSecretData contains the secret values from the User (a, b, c) and the
 80// public F
 81type UserSecretData struct {
 82	A *big.Int
 83	B *big.Int
 84	C *big.Int
 85
 86	F *blindsecp256k1.Point // public
 87}
 88
 89// Blind performs the blinding operation on m using SignerPublicData parameters
 90func Blind(m *big.Int, signerPubK *blindsecp256k1.PublicKey,
 91	signerR *blindsecp256k1.Point) (*big.Int, *UserSecretData, error) {
 92	var err error
 93	u := &UserSecretData{}
 94	u.A, err = newRand()
 95	if err != nil {
 96		return nil, nil, err
 97	}
 98	u.B, err = newRand()
 99	if err != nil {
100		return nil, nil, err
101	}
102	u.C, err = newRand()
103	if err != nil {
104		return nil, nil, err
105	}
106	binv := new(big.Int).ModInverse(u.B, blindsecp256k1.N)
107
108	// F = b^-1 R + a b^-1 Q + c G
109	bR := signerR.Mul(binv)
110	abinv := new(big.Int).Mul(u.A, binv)
111	abinv = new(big.Int).Mod(abinv, blindsecp256k1.N)
112	abQ := signerPubK.Point().Mul(abinv)
113	cG := blindsecp256k1.G.Mul(u.C)
114	u.F = bR.Add(abQ).Add(cG)
115	// TODO check F==O
116
117	r := new(big.Int).Mod(u.F.X, blindsecp256k1.N)
118
119	// m' = br(m)+a
120	br := new(big.Int).Mul(u.B, r)
121	brm := new(big.Int).Mul(br, m)
122	mBlinded := new(big.Int).Add(brm, u.A)
123	mBlinded = new(big.Int).Mod(mBlinded, blindsecp256k1.N)
124	return mBlinded, u, nil
125}
126
127// Signature contains the signature values S & F
128type Signature struct {
129	S *big.Int
130	F *blindsecp256k1.Point
131}
132
133// Unblind performs the unblinding operation of the blinded signature for the
134// given and the UserSecretData
135func Unblind(sBlind *big.Int, u *UserSecretData) *Signature {
136	// s = b^-1 s' + c
137	binv := new(big.Int).ModInverse(u.B, blindsecp256k1.N)
138	bs := new(big.Int).Mul(binv, sBlind)
139	s := new(big.Int).Add(bs, u.C)
140	s = new(big.Int).Mod(s, blindsecp256k1.N)
141
142	return &Signature{
143		S: s,
144		F: u.F,
145	}
146}
147
148// Verify checks the signature of the message m for the given PublicKey
149func Verify(m *big.Int, signature *Signature, q *blindsecp256k1.PublicKey) bool {
150	// TODO add pending checks
151	sG := blindsecp256k1.G.Mul(signature.S) // sG
152
153	r := new(big.Int).Mod(signature.F.X, blindsecp256k1.N) // r = Fx mod N
154	rm := new(big.Int).Mul(r, m)
155	rm = new(big.Int).Mod(rm, blindsecp256k1.N)
156	rmQ := q.Point().Mul(rm)
157	rmQF := rmQ.Add(signature.F) // rmQ + F
158
159	// check sG == rmQ + F
160	if bytes.Equal(sG.X.Bytes(), rmQF.X.Bytes()) &&
161		bytes.Equal(sG.Y.Bytes(), rmQF.Y.Bytes()) {
162		return true
163	}
164	return false
165}