Schnorr signature implemented. ECC point multiplication with big int. Refactor of the code.
jump to
@@ -1,14 +1,16 @@
package elgamal import ( - ecc "../ecc" + "math/big" + + "github.com/arnaucube/cryptofun/ecc" ) // EG is the ElGamal data structure type EG struct { EC ecc.EC G ecc.Point - N int + N *big.Int } // NewEG defines a new EG data structure@@ -22,19 +24,22 @@ return eg, err
} // PubK returns the public key Point calculated from the private key over the elliptic curve -func (eg EG) PubK(privK int) (ecc.Point, error) { +func (eg EG) PubK(privK *big.Int) (ecc.Point, error) { // privK: rand < ec.Q - pubK, err := eg.EC.Mul(eg.G, privK) + privKCopy := new(big.Int).SetBytes(privK.Bytes()) + pubK, err := eg.EC.Mul(eg.G, privKCopy) return pubK, err } // Encrypt encrypts a point m with the public key point, returns two points -func (eg EG) Encrypt(m ecc.Point, pubK ecc.Point, r int) ([2]ecc.Point, error) { - p1, err := eg.EC.Mul(eg.G, r) +func (eg EG) Encrypt(m ecc.Point, pubK ecc.Point, r *big.Int) ([2]ecc.Point, error) { + rCopy := new(big.Int).SetBytes(r.Bytes()) + p1, err := eg.EC.Mul(eg.G, rCopy) if err != nil { return [2]ecc.Point{}, err } - p2, err := eg.EC.Mul(pubK, r) + rCopy = new(big.Int).SetBytes(r.Bytes()) + p2, err := eg.EC.Mul(pubK, rCopy) if err != nil { return [2]ecc.Point{}, err }@@ -47,10 +52,11 @@ return c, err
} // Decrypt decrypts c (two points) with the private key, returns the point decrypted -func (eg EG) Decrypt(c [2]ecc.Point, privK int) (ecc.Point, error) { +func (eg EG) Decrypt(c [2]ecc.Point, privK *big.Int) (ecc.Point, error) { c1 := c[0] c2 := c[1] - c1PrivK, err := eg.EC.Mul(c1, privK) + privKCopy := new(big.Int).SetBytes(privK.Bytes()) + c1PrivK, err := eg.EC.Mul(c1, privKCopy) if err != nil { return ecc.Point{}, err }
@@ -4,21 +4,20 @@ import (
"math/big" "testing" - ecc "../ecc" + "github.com/arnaucube/cryptofun/ecc" + "github.com/stretchr/testify/assert" ) func TestNewEG(t *testing.T) { ec := ecc.NewEC(1, 18, 19) g := ecc.Point{big.NewInt(int64(7)), big.NewInt(int64(11))} eg, err := NewEG(ec, g) - if err != nil { - t.Errorf(err.Error()) - } - privK := 5 + assert.Nil(t, err) + + privK := big.NewInt(int64(5)) pubK, err := eg.PubK(privK) - if err != nil { - t.Errorf(err.Error()) - } + assert.Nil(t, err) + if !pubK.Equal(ecc.Point{big.NewInt(int64(13)), big.NewInt(int64(9))}) { t.Errorf("pubK!=(13, 9)") }@@ -27,20 +26,17 @@ func TestEGEncrypt(t *testing.T) {
ec := ecc.NewEC(1, 18, 19) g := ecc.Point{big.NewInt(int64(7)), big.NewInt(int64(11))} eg, err := NewEG(ec, g) - if err != nil { - t.Errorf(err.Error()) - } - privK := 5 + assert.Nil(t, err) + + privK := big.NewInt(int64(5)) pubK, err := eg.PubK(privK) - if err != nil { - t.Errorf(err.Error()) - } + assert.Nil(t, err) + // m: point to encrypt m := ecc.Point{big.NewInt(int64(11)), big.NewInt(int64(12))} - c, err := eg.Encrypt(m, pubK, 15) - if err != nil { - t.Errorf(err.Error()) - } + c, err := eg.Encrypt(m, pubK, big.NewInt(int64(15))) + assert.Nil(t, err) + if !c[0].Equal(ecc.Point{big.NewInt(int64(8)), big.NewInt(int64(5))}) { t.Errorf("c[0] != (8, 5), encryption failed") }@@ -53,24 +49,20 @@ func TestEGDecrypt(t *testing.T) {
ec := ecc.NewEC(1, 18, 19) g := ecc.Point{big.NewInt(int64(7)), big.NewInt(int64(11))} eg, err := NewEG(ec, g) - if err != nil { - t.Errorf(err.Error()) - } - privK := 5 + assert.Nil(t, err) + + privK := big.NewInt(int64(5)) pubK, err := eg.PubK(privK) - if err != nil { - t.Errorf(err.Error()) - } + assert.Nil(t, err) + // m: point to encrypt m := ecc.Point{big.NewInt(int64(11)), big.NewInt(int64(12))} - c, err := eg.Encrypt(m, pubK, 15) - if err != nil { - t.Errorf(err.Error()) - } + c, err := eg.Encrypt(m, pubK, big.NewInt(int64(15))) + assert.Nil(t, err) + d, err := eg.Decrypt(c, privK) - if err != nil { - t.Errorf(err.Error()) - } + assert.Nil(t, err) + if !m.Equal(d) { t.Errorf("m != d, decrypting failed") }
@@ -1,4 +1,4 @@
-# cryptofun [](https://goreportcard.com/report/github.com/arnaucode/cryptofun) +# cryptofun [](https://goreportcard.com/report/github.com/arnaucube/cryptofun) Crypto algorithms from scratch. Academic purposes only.@@ -51,6 +51,12 @@ - [x] ECDSA Sign
- [x] ECDSA Verify signature +## Schnorr signature +https://en.wikipedia.org/wiki/Schnorr_signature +- [x] Hash[M || R] (where M is the msg bytes and R is a Point on the ECC, using sha256 hash function) +- [x] Generate Schnorr scheme +- [x] Sign +- [x] Verify signature ---
@@ -4,6 +4,8 @@ import (
"crypto/rand" "math/big" "testing" + + "github.com/stretchr/testify/assert" ) const (@@ -12,26 +14,19 @@ )
func TestDiffieHellman(t *testing.T) { p, err := rand.Prime(rand.Reader, bits/2) - if err != nil { - t.Errorf(err.Error()) - } + assert.Nil(t, err) + g, err := rand.Prime(rand.Reader, bits/2) - if err != nil { - t.Errorf(err.Error()) - } + assert.Nil(t, err) max, err := rand.Prime(rand.Reader, bits/2) - if err != nil { - t.Errorf(err.Error()) - } + assert.Nil(t, err) + a, err := rand.Int(rand.Reader, max) - if err != nil { - t.Errorf(err.Error()) - } + assert.Nil(t, err) + b, err := rand.Int(rand.Reader, max) - if err != nil { - t.Errorf(err.Error()) - } + assert.Nil(t, err) A := new(big.Int).Exp(g, a, p) B := new(big.Int).Exp(g, b, p)
@@ -49,20 +49,6 @@ // TODO get error when point not found on the ec
return Point{p.X, new(big.Int).Sub(ec.Q, p.Y)} } -// Order returns smallest n where nG = O (point at zero) -func (ec *EC) Order(g Point) (int, error) { - for i := 1; i < int(ec.Q.Int64())+1; i++ { - mPoint, err := ec.Mul(g, i) - if err != nil { - return i, err - } - if mPoint.Equal(zeroPoint) { - return i, nil - } - } - return -1, errors.New("invalid order") -} - // Add adds two points p1 and p2 and gets q, returns the negate of q func (ec *EC) Add(p1, p2 Point) (Point, error) { if p1.Equal(zeroPoint) {@@ -126,23 +112,41 @@ return q, nil
} // Mul multiplies a point n times on the elliptic curve -func (ec *EC) Mul(p Point, n int) (Point, error) { +func (ec *EC) Mul(p Point, n *big.Int) (Point, error) { var err error p2 := p r := zeroPoint - for 0 < n { - if n&1 == 1 { + for bigZero.Cmp(n) == -1 { // 0<n + z := new(big.Int).And(n, bigOne) // n&1 + if bytes.Equal(z.Bytes(), bigOne.Bytes()) { // n&1==1 r, err = ec.Add(r, p2) if err != nil { return p, err } } - n = n >> 1 + n = n.Rsh(n, 1) // n = n>>1 p2, err = ec.Add(p2, p2) if err != nil { return p, err } - } return r, nil } + +// Order returns smallest n where nG = O (point at zero) +func (ec *EC) Order(g Point) (*big.Int, error) { + // loop from i:=1 to i<ec.Q+1 + start := big.NewInt(1) + end := new(big.Int).Add(ec.Q, bigOne) + for i := new(big.Int).Set(start); i.Cmp(end) <= 0; i.Add(i, bigOne) { + iCopy := new(big.Int).SetBytes(i.Bytes()) + mPoint, err := ec.Mul(g, iCopy) + if err != nil { + return i, err + } + if mPoint.Equal(zeroPoint) { + return i, nil + } + } + return bigZero, errors.New("invalid order") +}
@@ -1,17 +1,17 @@
package ecc import ( - "fmt" "math/big" "testing" + + "github.com/stretchr/testify/assert" ) func TestECC(t *testing.T) { ec := NewEC(0, 7, 11) p1, p1i, err := ec.At(big.NewInt(int64(7))) - if err != nil { - t.Errorf(err.Error()) - } + assert.Nil(t, err) + if !p1.Equal(Point{big.NewInt(int64(7)), big.NewInt(int64(3))}) { t.Errorf("p1!=(7, 11)") }@@ -22,32 +22,30 @@ }
func TestNeg(t *testing.T) { ec := NewEC(0, 7, 11) p1, p1i, err := ec.At(big.NewInt(int64(7))) - if err != nil { - t.Errorf(err.Error()) - } + assert.Nil(t, err) + p1Neg := ec.Neg(p1) if !p1Neg.Equal(p1i) { t.Errorf("p1Neg!=p1i") } } + func TestAdd(t *testing.T) { ec := NewEC(0, 7, 11) p1 := Point{big.NewInt(int64(4)), big.NewInt(int64(7))} p2 := Point{big.NewInt(int64(2)), big.NewInt(int64(2))} q, err := ec.Add(p1, p2) - if err != nil { - t.Errorf(err.Error()) - } + assert.Nil(t, err) + if !q.Equal(Point{big.NewInt(int64(3)), big.NewInt(int64(1))}) { t.Errorf("q!=(3, 1)") } // check that q exists on the elliptic curve pt, pti, err := ec.At(q.X) - if err != nil { - t.Errorf(err.Error()) - } + assert.Nil(t, err) + if !q.Equal(pt) && !q.Equal(pti) { t.Errorf("q not exist on the elliptic curve") }@@ -60,69 +58,155 @@ p1 := Point{big.NewInt(int64(4)), big.NewInt(int64(7))}
p1i := Point{big.NewInt(int64(4)), big.NewInt(int64(4))} q, err := ec.Add(p1, p1) - if err != nil { - t.Errorf(err.Error()) - } + assert.Nil(t, err) + if !q.Equal(Point{big.NewInt(int64(6)), big.NewInt(int64(5))}) { - t.Errorf("q!=(6, 5)") + t.Errorf(q.String() + " == q != (6, 5)") } q_, err := ec.Add(p1i, p1i) - if err != nil { - t.Errorf(err.Error()) - } + assert.Nil(t, err) + if !q_.Equal(Point{big.NewInt(int64(6)), big.NewInt(int64(6))}) { - t.Errorf("q_!=(6, 6)") + t.Errorf(q_.String() + " == q_ != (6, 6)") } } -func TestMulEqualSelfAdd(t *testing.T) { +func TestMulPoint1(t *testing.T) { ec := NewEC(0, 7, 29) - p1 := Point{big.NewInt(int64(11)), big.NewInt(int64(27))} + p := Point{big.NewInt(int64(11)), big.NewInt(int64(27))} - p1p1, err := ec.Add(p1, p1) - if err != nil { - t.Errorf(err.Error()) + q, err := ec.Mul(p, big.NewInt(int64(1))) + assert.Nil(t, err) + + if !q.Equal(Point{big.NewInt(int64(11)), big.NewInt(int64(27))}) { + t.Errorf(q.String() + " == q != (11, 27)") } - p1p1, err = ec.Add(p1p1, p1) - if err != nil { - t.Errorf(err.Error()) + + q, err = ec.Mul(p, big.NewInt(int64(2))) + assert.Nil(t, err) + + if !q.Equal(Point{big.NewInt(int64(12)), big.NewInt(int64(13))}) { + t.Errorf(q.String() + " == q != (12, 13)") } - q, err := ec.Mul(p1, 3) - if err != nil { - t.Errorf(err.Error()) + + q, err = ec.Mul(p, big.NewInt(int64(3))) + assert.Nil(t, err) + + if !q.Equal(Point{big.NewInt(int64(28)), big.NewInt(int64(8))}) { + t.Errorf(q.String() + " == q != (28, 8)") } - if !q.Equal(p1p1) { - fmt.Println(q) - fmt.Println(p1p1) - t.Errorf("q!=p1*p1") + + q, err = ec.Mul(p, big.NewInt(int64(4))) + assert.Nil(t, err) + + if !q.Equal(Point{big.NewInt(int64(6)), big.NewInt(int64(22))}) { + t.Errorf(q.String() + " == q != (6, 22)") } } -func TestMul(t *testing.T) { +func TestMulPoint2(t *testing.T) { ec := NewEC(0, 7, 29) p1 := Point{big.NewInt(int64(4)), big.NewInt(int64(19))} - q3, err := ec.Mul(p1, 3) - if err != nil { - t.Errorf(err.Error()) - } + q3, err := ec.Mul(p1, big.NewInt(int64(3))) + assert.Nil(t, err) + if !q3.Equal(Point{big.NewInt(int64(6)), big.NewInt(int64(7))}) { - t.Errorf("q3!=(6, 7)") + t.Errorf(q3.String() + " == q3 != (6, 7)") } - q7, err := ec.Mul(p1, 7) - if err != nil { - t.Errorf(err.Error()) - } + q7, err := ec.Mul(p1, big.NewInt(int64(7))) + assert.Nil(t, err) + if !q7.Equal(Point{big.NewInt(int64(19)), big.NewInt(int64(14))}) { - t.Errorf("q7!=(19, 14)") + t.Errorf(q7.String() + " == q7 != (19, 14)") } - q8, err := ec.Mul(p1, 8) - if err != nil { - t.Errorf(err.Error()) + q8, err := ec.Mul(p1, big.NewInt(int64(8))) + assert.Nil(t, err) + + if !q8.Equal(Point{big.NewInt(int64(19)), big.NewInt(int64(15))}) { + t.Errorf(q8.String() + " == q8 != (12, 16)") + } +} + +func TestMulPoint3(t *testing.T) { + // in this test we will multiply by a high number + ec := NewEC(0, 7, 11) + p := Point{big.NewInt(int64(7)), big.NewInt(int64(3))} + + q, err := ec.Mul(p, big.NewInt(int64(100))) + assert.Nil(t, err) + if !q.Equal(Point{big.NewInt(int64(3)), big.NewInt(int64(1))}) { + t.Errorf(q.String() + " == q != (3, 1)") } - if !q8.Equal(Point{big.NewInt(int64(19)), big.NewInt(int64(15))}) { - t.Errorf("q8!=(19, 15)") + + q, err = ec.Mul(p, big.NewInt(int64(100))) + assert.Nil(t, err) + if !q.Equal(Point{big.NewInt(int64(3)), big.NewInt(int64(1))}) { + t.Errorf(q.String() + " == q != (3, 1)") } } + +func TestMulEqualSelfAdd(t *testing.T) { + ec := NewEC(0, 7, 29) + p1 := Point{big.NewInt(int64(11)), big.NewInt(int64(27))} + + p1_2, err := ec.Add(p1, p1) + assert.Nil(t, err) + + p1_3, err := ec.Add(p1_2, p1) + assert.Nil(t, err) + + // q * 3 + q, err := ec.Mul(p1, big.NewInt(int64(3))) + assert.Nil(t, err) + + if !q.Equal(Point{big.NewInt(int64(28)), big.NewInt(int64(8))}) { + t.Errorf(q.String() + " == q != (28, 8)") + } + if !q.Equal(p1_3) { + t.Errorf("p*3 == " + q.String() + ", p+p+p == " + p1_3.String()) + } + + // q * 4 + p1_4, err := ec.Add(p1_3, p1) + assert.Nil(t, err) + + q, err = ec.Mul(p1, big.NewInt(int64(4))) + assert.Nil(t, err) + + if !q.Equal(Point{big.NewInt(int64(6)), big.NewInt(int64(22))}) { + t.Errorf(q.String() + " == q != (6, 22)") + } + if !q.Equal(p1_4) { + t.Errorf("p*4 == " + q.String() + ", p+p+p+p == " + p1_4.String()) + } +} + +func TestOrder(t *testing.T) { + ec := NewEC(0, 7, 11) + g := Point{big.NewInt(int64(7)), big.NewInt(int64(8))} + order, err := ec.Order(g) + assert.Nil(t, err) + assert.Equal(t, order.Int64(), int64(12)) + + // another test + g = Point{big.NewInt(int64(2)), big.NewInt(int64(9))} + order, err = ec.Order(g) + assert.Nil(t, err) + assert.Equal(t, order.Int64(), int64(4)) + + // another test with another curve + ec = NewEC(0, 7, 29) + g = Point{big.NewInt(int64(6)), big.NewInt(int64(22))} + order, err = ec.Order(g) + assert.Nil(t, err) + assert.Equal(t, order.Int64(), int64(5)) + + // another test + g = Point{big.NewInt(int64(23)), big.NewInt(int64(9))} + order, err = ec.Order(g) + assert.Nil(t, err) + assert.Equal(t, order.Int64(), int64(30)) +}
@@ -7,6 +7,7 @@ )
var ( bigZero = big.NewInt(int64(0)) + bigOne = big.NewInt(int64(1)) zeroPoint = Point{bigZero, bigZero} )@@ -26,3 +27,8 @@ return false
} return true } + +// String returns the components of the point in a string +func (p *Point) String() string { + return "(" + p.X.String() + ", " + p.Y.String() + ")" +}
@@ -4,14 +4,15 @@ import (
"bytes" "math/big" - ecc "../ecc" + // ecc "../ecc" + "github.com/arnaucube/cryptofun/ecc" ) // DSA is the ECDSA data structure type DSA struct { EC ecc.EC G ecc.Point - N int + N *big.Int } // NewDSA defines a new DSA data structure@@ -25,40 +26,48 @@ return dsa, err
} // PubK returns the public key Point calculated from the private key over the elliptic curve -func (dsa DSA) PubK(privK int) (ecc.Point, error) { +func (dsa DSA) PubK(privK *big.Int) (ecc.Point, error) { // privK: rand < ec.Q - pubK, err := dsa.EC.Mul(dsa.G, privK) + privKCopy := new(big.Int).SetBytes(privK.Bytes()) + pubK, err := dsa.EC.Mul(dsa.G, privKCopy) return pubK, err } -func (dsa DSA) Sign(hashval *big.Int, privK int, r *big.Int) ([2]*big.Int, error) { - m, err := dsa.EC.Mul(dsa.G, int(r.Int64())) + +// Sign performs the ECDSA signature +func (dsa DSA) Sign(hashval *big.Int, privK *big.Int, r *big.Int) ([2]*big.Int, error) { + rCopy := new(big.Int).SetBytes(r.Bytes()) + m, err := dsa.EC.Mul(dsa.G, rCopy) if err != nil { return [2]*big.Int{}, err } // inv(r) mod dsa.N - inv := new(big.Int).ModInverse(r, big.NewInt(int64(dsa.N))) + inv := new(big.Int).ModInverse(r, dsa.N) // m.X * privK - xPrivK := new(big.Int).Mul(m.X, big.NewInt(int64(privK))) + privKCopy := new(big.Int).SetBytes(privK.Bytes()) + xPrivK := new(big.Int).Mul(m.X, privKCopy) // (hashval + m.X * privK) hashvalXPrivK := new(big.Int).Add(hashval, xPrivK) // inv * (hashval + m.X * privK) mod dsa.N a := new(big.Int).Mul(inv, hashvalXPrivK) - r2 := new(big.Int).Mod(a, big.NewInt(int64(dsa.N))) + r2 := new(big.Int).Mod(a, dsa.N) return [2]*big.Int{m.X, r2}, err } +// Verify validates the ECDSA signature func (dsa DSA) Verify(hashval *big.Int, sig [2]*big.Int, pubK ecc.Point) (bool, error) { - w := new(big.Int).ModInverse(sig[1], big.NewInt(int64(dsa.N))) - u1raw := new(big.Int).Mul(hashval, w) - u1 := new(big.Int).Mod(u1raw, big.NewInt(int64(dsa.N))) - u2raw := new(big.Int).Mul(sig[0], w) - u2 := new(big.Int).Mod(u2raw, big.NewInt(int64(dsa.N))) + w := new(big.Int).ModInverse(sig[1], dsa.N) + wCopy := new(big.Int).SetBytes(w.Bytes()) + u1raw := new(big.Int).Mul(hashval, wCopy) + u1 := new(big.Int).Mod(u1raw, dsa.N) + wCopy = new(big.Int).SetBytes(w.Bytes()) + u2raw := new(big.Int).Mul(sig[0], wCopy) + u2 := new(big.Int).Mod(u2raw, dsa.N) - gU1, err := dsa.EC.Mul(dsa.G, int(u1.Int64())) + gU1, err := dsa.EC.Mul(dsa.G, u1) if err != nil { return false, err } - pubKU2, err := dsa.EC.Mul(pubK, int(u2.Int64())) + pubKU2, err := dsa.EC.Mul(pubK, u2) if err != nil { return false, err }@@ -66,6 +75,6 @@ p, err := dsa.EC.Add(gU1, pubKU2)
if err != nil { return false, err } - pXmodN := new(big.Int).Mod(p.X, big.NewInt(int64(dsa.N))) + pXmodN := new(big.Int).Mod(p.X, dsa.N) return bytes.Equal(pXmodN.Bytes(), sig[0].Bytes()), nil }
@@ -4,21 +4,20 @@ import (
"math/big" "testing" - ecc "../ecc" + "github.com/arnaucube/cryptofun/ecc" + "github.com/stretchr/testify/assert" ) func TestNewECDSA(t *testing.T) { ec := ecc.NewEC(1, 18, 19) g := ecc.Point{big.NewInt(int64(7)), big.NewInt(int64(11))} dsa, err := NewDSA(ec, g) - if err != nil { - t.Errorf(err.Error()) - } - privK := 5 + assert.Nil(t, err) + + privK := big.NewInt(int64(5)) pubK, err := dsa.PubK(privK) - if err != nil { - t.Errorf(err.Error()) - } + assert.Nil(t, err) + if !pubK.Equal(ecc.Point{big.NewInt(int64(13)), big.NewInt(int64(9))}) { t.Errorf("pubK!=(13, 9)") }@@ -28,24 +27,18 @@ func TestECDSASignAndVerify(t *testing.T) {
ec := ecc.NewEC(1, 18, 19) g := ecc.Point{big.NewInt(int64(7)), big.NewInt(int64(11))} dsa, err := NewDSA(ec, g) - if err != nil { - t.Errorf(err.Error()) - } - privK := 5 + assert.Nil(t, err) + + privK := big.NewInt(int64(5)) pubK, err := dsa.PubK(privK) - if err != nil { - t.Errorf(err.Error()) - } + assert.Nil(t, err) + hashval := big.NewInt(int64(40)) r := big.NewInt(int64(11)) sig, err := dsa.Sign(hashval, privK, r) - if err != nil { - t.Errorf(err.Error()) - } + assert.Nil(t, err) verified, err := dsa.Verify(hashval, sig, pubK) - if !verified { - t.Errorf("verified == false") - } + assert.True(t, verified) }
@@ -0,0 +1,7 @@
+module github.com/arnaucube/cryptofun + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/stretchr/testify v1.2.2 +)
@@ -0,0 +1,6 @@
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
@@ -5,7 +5,8 @@ "crypto/rand"
"errors" "math/big" - prime "../prime" + // prime "../prime" + "github.com/arnaucube/cryptofun/prime" ) const (
@@ -5,13 +5,14 @@ "bytes"
"fmt" "math/big" "testing" + + "github.com/stretchr/testify/assert" ) func TestEncryptDecrypt(t *testing.T) { key, err := GenerateKeyPair() - if err != nil { - t.Errorf(err.Error()) - } + assert.Nil(t, err) + mBytes := []byte("Hi") m := new(big.Int).SetBytes(mBytes) c := Encrypt(m, key.PubK)@@ -24,9 +25,8 @@ }
func TestHomomorphicAddition(t *testing.T) { key, err := GenerateKeyPair() - if err != nil { - t.Errorf(err.Error()) - } + assert.Nil(t, err) + n1 := big.NewInt(int64(110)) n2 := big.NewInt(int64(150)) c1 := Encrypt(n1, key.PubK)
@@ -4,13 +4,14 @@ import (
"bytes" "math/big" "testing" + + "github.com/stretchr/testify/assert" ) func TestEncryptDecrypt(t *testing.T) { key, err := GenerateKeyPair() - if err != nil { - t.Errorf(err.Error()) - } + assert.Nil(t, err) + mBytes := []byte("Hi") m := new(big.Int).SetBytes(mBytes) c := Encrypt(m, key.PubK)@@ -22,9 +23,7 @@ }
} func TestBlindSignature(t *testing.T) { key, err := GenerateKeyPair() - if err != nil { - t.Errorf(err.Error()) - } + assert.Nil(t, err) mBytes := []byte("Hi") m := new(big.Int).SetBytes(mBytes)@@ -46,9 +45,7 @@ }
func TestHomomorphicMultiplication(t *testing.T) { key, err := GenerateKeyPair() - if err != nil { - t.Errorf(err.Error()) - } + assert.Nil(t, err) n1 := big.NewInt(int64(11)) n2 := big.NewInt(int64(15))
@@ -0,0 +1,136 @@
+package schnorr + +import ( + "crypto/rand" + "crypto/sha256" + "math/big" + + "github.com/arnaucube/cryptofun/ecc" +) + +const ( + bits = 512 // 2048 +) + +// PubK is the public key of the Schnorr scheme +type PubK struct { + P ecc.Point + Q ecc.Point +} + +// PrivK is the private key of the Schnorr scheme +type PrivK struct { + PubK PubK + A *big.Int +} + +// Schnorr is the data structure for the Schnorr scheme +type Schnorr struct { + EC ecc.EC + D *big.Int // K + G ecc.Point + Q ecc.Point // P + N int // order of curve +} + +// Hash calculates a hash concatenating a given message bytes with a given EC Point. H(M||R) +func Hash(m []byte, c ecc.Point) *big.Int { + var b []byte + b = append(b, m...) + cXBytes := c.X.Bytes() + cYBytes := c.Y.Bytes() + b = append(b, cXBytes...) + b = append(b, cYBytes...) + h := sha256.New() + h.Write(b) + hash := h.Sum(nil) + r := new(big.Int).SetBytes(hash) + return r +} + +// Gen generates the Schnorr scheme +func Gen(ec ecc.EC, g ecc.Point, r *big.Int) (Schnorr, PrivK, error) { + var err error + var schnorr Schnorr + var sk PrivK + schnorr.EC = ec + schnorr.G = g + + sk.PubK.P, _, err = ec.At(r) + if err != nil { + return schnorr, sk, err + } + + orderP, err := ec.Order(sk.PubK.P) + if err != nil { + return schnorr, sk, err + } + + // rand int between 1 and oerder of P + sk.A, err = rand.Int(rand.Reader, orderP) + if err != nil { + return schnorr, sk, err + } + sk.A = big.NewInt(int64(7)) + skACopy := new(big.Int).SetBytes(sk.A.Bytes()) + // pk.Q = k x P + sk.PubK.Q, err = ec.Mul(sk.PubK.P, skACopy) + if err != nil { + return schnorr, sk, err + } + return schnorr, sk, nil +} + +// Sign performs the signature of the message m with the given private key +func (schnorr Schnorr) Sign(sk PrivK, m []byte) (*big.Int, ecc.Point, error) { + var e *big.Int + orderP, err := schnorr.EC.Order(sk.PubK.P) + if err != nil { + return e, ecc.Point{}, err + } + // rand k <-[1,r] + k, err := rand.Int(rand.Reader, orderP) + if err != nil { + return e, ecc.Point{}, err + } + + // R = k x P + rPoint, err := schnorr.EC.Mul(sk.PubK.P, k) + if err != nil { + return e, ecc.Point{}, err + } + // e = H(M||R) + e = Hash(m, rPoint) + // a*e + ae := new(big.Int).Mul(sk.A, e) + // k + a*e + kae := new(big.Int).Add(k, ae) + // k + a*e mod r, where r is order of P + s := new(big.Int).Mod(kae, orderP) + return s, rPoint, nil +} + +// Verify checks if the given public key matches with the given signature of the message m, in the given EC +func Verify(ec ecc.EC, pk PubK, m []byte, s *big.Int, rPoint ecc.Point) (bool, error) { + // e = H(M||R) + e := Hash(m, rPoint) + eCopy := new(big.Int).SetBytes(e.Bytes()) + + // e x Q + eQ, err := ec.Mul(pk.Q, eCopy) + if err != nil { + return false, err + } + + // R + e x Q + // reQ, err := schnorr.EC.Add(rPoint, eQ) + // if err != nil { + // return false, err + // } + + // s x P + sp, err := ec.Mul(pk.P, s) + + // return reQ.Equal(sp), nil + return eQ.Equal(sp), nil +}
@@ -0,0 +1,65 @@
+package schnorr + +import ( + "math/big" + "testing" + + "github.com/arnaucube/cryptofun/ecc" + "github.com/stretchr/testify/assert" +) + +// func TestNewSystem(t *testing.T) { +// +// ec := ecc.NewEC(0, 7, 11) +// g := ecc.Point{big.NewInt(int64(7)), big.NewInt(int64(8))} // Generator +// r := big.NewInt(int64(7)) // random r +// schnorr, sk, err := Gen(ec, g, r) +// assert.Nil(t, err) +// +// fmt.Print("schnorr") +// fmt.Println(schnorr) +// fmt.Print("sk") +// fmt.Println(sk) +// } + +func TestHash(t *testing.T) { + c := ecc.Point{big.NewInt(int64(7)), big.NewInt(int64(8))} // Generator + h := Hash([]byte("hola"), c) + assert.Equal(t, h.String(), "34719153732582497359642109898768696927847420320548121616059449972754491425079") +} + +func TestSign(t *testing.T) { + ec := ecc.NewEC(0, 7, 11) + g := ecc.Point{big.NewInt(int64(7)), big.NewInt(int64(8))} // Generator + r := big.NewInt(int64(7)) // random r + schnorr, sk, err := Gen(ec, g, r) + assert.Nil(t, err) + + m := []byte("hola") + + s, rPoint, err := schnorr.Sign(sk, m) + assert.Nil(t, err) + + verified, err := Verify(schnorr.EC, sk.PubK, m, s, rPoint) + assert.Nil(t, err) + + assert.True(t, verified) +} + +func TestSign2(t *testing.T) { + ec := ecc.NewEC(0, 7, 29) + g := ecc.Point{big.NewInt(int64(11)), big.NewInt(int64(27))} // Generator + r := big.NewInt(int64(23)) // random r + schnorr, sk, err := Gen(ec, g, r) + assert.Nil(t, err) + + m := []byte("hola") + + s, rPoint, err := schnorr.Sign(sk, m) + assert.Nil(t, err) + + verified, err := Verify(schnorr.EC, sk.PubK, m, s, rPoint) + assert.Nil(t, err) + + assert.True(t, verified) +}
@@ -1,17 +1,17 @@
-package secrets +package shamirsecretsharing import ( "crypto/rand" "math/big" "testing" + + "github.com/stretchr/testify/assert" ) func TestCreate(t *testing.T) { k := 123456789 p, err := rand.Prime(rand.Reader, bits/2) - if err != nil { - t.Errorf(err.Error()) - } + assert.Nil(t, err) nNeededSecrets := big.NewInt(int64(3)) nShares := big.NewInt(int64(6))@@ -20,9 +20,7 @@ nNeededSecrets,
nShares, p, big.NewInt(int64(k))) - if err != nil { - t.Errorf(err.Error()) - } + assert.Nil(t, err) //generate sharesToUse var sharesToUse [][]*big.Int
@@ -1,4 +1,4 @@
-package secrets +package shamirsecretsharing import ( "crypto/rand"@@ -10,11 +10,11 @@ const (
bits = 1024 ) -// Create calculates the secrets to share from given parameters // t: number of secrets needed // n: number of shares // p: random point // k: secret to share +// Create calculates the secrets to share from given parameters func Create(t, n, p, k *big.Int) (result [][]*big.Int, err error) { if k.Cmp(p) > 0 { return nil, errors.New("Error: need k<p. k: " + k.String() + ", p: " + p.String())