Browse Source

Schnorr signature implemented. ECC point multiplication with big int. Refactor of the code.

master
arnaucube 6 years ago
parent
commit
4acca94c9e
19 changed files with 498 additions and 192 deletions
  1. +1
    -0
      .gitignore
  2. +7
    -1
      README.md
  3. +10
    -15
      dh/dh_test.go
  4. +23
    -19
      ecc/ecc.go
  5. +136
    -52
      ecc/ecc_test.go
  6. +6
    -0
      ecc/point.go
  7. +26
    -17
      ecdsa/ecdsa.go
  8. +14
    -21
      ecdsa/ecdsa_test.go
  9. +15
    -9
      elgamal/elgamal.go
  10. +25
    -33
      elgamal/elgamal_test.go
  11. +7
    -0
      go.mod
  12. +6
    -0
      go.sum
  13. +2
    -1
      paillier/paillier.go
  14. +6
    -6
      paillier/paillier_test.go
  15. +6
    -9
      rsa/rsa_test.go
  16. +136
    -0
      schnorr/schnorr.go
  17. +65
    -0
      schnorr/schnorr_test.go
  18. +2
    -2
      shamirsecretsharing/shamirsecretsharing.go
  19. +5
    -7
      shamirsecretsharing/shamirsecretsharing_test.go

+ 1
- 0
.gitignore

@ -1 +1,2 @@
fmt fmt
schnorr.goBACKUP

+ 7
- 1
README.md

@ -1,4 +1,4 @@
# cryptofun [![Go Report Card](https://goreportcard.com/badge/github.com/arnaucode/cryptofun)](https://goreportcard.com/report/github.com/arnaucode/cryptofun)
# cryptofun [![Go Report Card](https://goreportcard.com/badge/github.com/arnaucube/cryptofun)](https://goreportcard.com/report/github.com/arnaucube/cryptofun)
Crypto algorithms from scratch. Academic purposes only. Crypto algorithms from scratch. Academic purposes only.
@ -51,6 +51,12 @@ https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm
- [x] ECDSA Verify signature - [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
--- ---

+ 10
- 15
dh/dh_test.go

@ -4,6 +4,8 @@ import (
"crypto/rand" "crypto/rand"
"math/big" "math/big"
"testing" "testing"
"github.com/stretchr/testify/assert"
) )
const ( const (
@ -12,26 +14,19 @@ const (
func TestDiffieHellman(t *testing.T) { func TestDiffieHellman(t *testing.T) {
p, err := rand.Prime(rand.Reader, bits/2) 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) 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) 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) 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) 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) A := new(big.Int).Exp(g, a, p)
B := new(big.Int).Exp(g, b, p) B := new(big.Int).Exp(g, b, p)

+ 23
- 19
ecc/ecc.go

@ -49,20 +49,6 @@ func (ec *EC) Neg(p Point) Point {
return Point{p.X, new(big.Int).Sub(ec.Q, p.Y)} 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 // Add adds two points p1 and p2 and gets q, returns the negate of q
func (ec *EC) Add(p1, p2 Point) (Point, error) { func (ec *EC) Add(p1, p2 Point) (Point, error) {
if p1.Equal(zeroPoint) { if p1.Equal(zeroPoint) {
@ -126,23 +112,41 @@ func (ec *EC) Add(p1, p2 Point) (Point, error) {
} }
// Mul multiplies a point n times on the elliptic curve // 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 var err error
p2 := p p2 := p
r := zeroPoint 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) r, err = ec.Add(r, p2)
if err != nil { if err != nil {
return p, err return p, err
} }
} }
n = n >> 1
n = n.Rsh(n, 1) // n = n>>1
p2, err = ec.Add(p2, p2) p2, err = ec.Add(p2, p2)
if err != nil { if err != nil {
return p, err return p, err
} }
} }
return r, nil 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")
}

+ 136
- 52
ecc/ecc_test.go

@ -1,17 +1,17 @@
package ecc package ecc
import ( import (
"fmt"
"math/big" "math/big"
"testing" "testing"
"github.com/stretchr/testify/assert"
) )
func TestECC(t *testing.T) { func TestECC(t *testing.T) {
ec := NewEC(0, 7, 11) ec := NewEC(0, 7, 11)
p1, p1i, err := ec.At(big.NewInt(int64(7))) 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))}) { if !p1.Equal(Point{big.NewInt(int64(7)), big.NewInt(int64(3))}) {
t.Errorf("p1!=(7, 11)") t.Errorf("p1!=(7, 11)")
} }
@ -22,32 +22,30 @@ func TestECC(t *testing.T) {
func TestNeg(t *testing.T) { func TestNeg(t *testing.T) {
ec := NewEC(0, 7, 11) ec := NewEC(0, 7, 11)
p1, p1i, err := ec.At(big.NewInt(int64(7))) p1, p1i, err := ec.At(big.NewInt(int64(7)))
if err != nil {
t.Errorf(err.Error())
}
assert.Nil(t, err)
p1Neg := ec.Neg(p1) p1Neg := ec.Neg(p1)
if !p1Neg.Equal(p1i) { if !p1Neg.Equal(p1i) {
t.Errorf("p1Neg!=p1i") t.Errorf("p1Neg!=p1i")
} }
} }
func TestAdd(t *testing.T) { func TestAdd(t *testing.T) {
ec := NewEC(0, 7, 11) ec := NewEC(0, 7, 11)
p1 := Point{big.NewInt(int64(4)), big.NewInt(int64(7))} p1 := Point{big.NewInt(int64(4)), big.NewInt(int64(7))}
p2 := Point{big.NewInt(int64(2)), big.NewInt(int64(2))} p2 := Point{big.NewInt(int64(2)), big.NewInt(int64(2))}
q, err := ec.Add(p1, p2) 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))}) { if !q.Equal(Point{big.NewInt(int64(3)), big.NewInt(int64(1))}) {
t.Errorf("q!=(3, 1)") t.Errorf("q!=(3, 1)")
} }
// check that q exists on the elliptic curve // check that q exists on the elliptic curve
pt, pti, err := ec.At(q.X) 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) { if !q.Equal(pt) && !q.Equal(pti) {
t.Errorf("q not exist on the elliptic curve") t.Errorf("q not exist on the elliptic curve")
} }
@ -60,69 +58,155 @@ func TestAddSamePoint(t *testing.T) {
p1i := Point{big.NewInt(int64(4)), big.NewInt(int64(4))} p1i := Point{big.NewInt(int64(4)), big.NewInt(int64(4))}
q, err := ec.Add(p1, p1) 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))}) { 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) 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))}) { 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) 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))}
q, err := ec.Mul(p, big.NewInt(int64(1)))
assert.Nil(t, err)
p1p1, err := ec.Add(p1, p1)
if err != nil {
t.Errorf(err.Error())
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) ec := NewEC(0, 7, 29)
p1 := Point{big.NewInt(int64(4)), big.NewInt(int64(19))} 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))}) { if !q3.Equal(Point{big.NewInt(int64(6)), big.NewInt(int64(7))}) {
t.Errorf("q3!=(6, 7)")
}
q7, err := ec.Mul(p1, 7)
if err != nil {
t.Errorf(err.Error())
t.Errorf(q3.String() + " == q3 != (6, 7)")
} }
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))}) { 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))}) { if !q8.Equal(Point{big.NewInt(int64(19)), big.NewInt(int64(15))}) {
t.Errorf("q8!=(19, 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)")
}
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))
} }

+ 6
- 0
ecc/point.go

@ -7,6 +7,7 @@ import (
var ( var (
bigZero = big.NewInt(int64(0)) bigZero = big.NewInt(int64(0))
bigOne = big.NewInt(int64(1))
zeroPoint = Point{bigZero, bigZero} zeroPoint = Point{bigZero, bigZero}
) )
@ -26,3 +27,8 @@ func (c1 *Point) Equal(c2 Point) bool {
} }
return true return true
} }
// String returns the components of the point in a string
func (p *Point) String() string {
return "(" + p.X.String() + ", " + p.Y.String() + ")"
}

+ 26
- 17
ecdsa/ecdsa.go

@ -4,14 +4,15 @@ import (
"bytes" "bytes"
"math/big" "math/big"
ecc "../ecc"
// ecc "../ecc"
"github.com/arnaucube/cryptofun/ecc"
) )
// DSA is the ECDSA data structure // DSA is the ECDSA data structure
type DSA struct { type DSA struct {
EC ecc.EC EC ecc.EC
G ecc.Point G ecc.Point
N int
N *big.Int
} }
// NewDSA defines a new DSA data structure // NewDSA defines a new DSA data structure
@ -25,40 +26,48 @@ func NewDSA(ec ecc.EC, g ecc.Point) (DSA, error) {
} }
// PubK returns the public key Point calculated from the private key over the elliptic curve // 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 // 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 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 { if err != nil {
return [2]*big.Int{}, err return [2]*big.Int{}, err
} }
// inv(r) mod dsa.N // 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 // 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) // (hashval + m.X * privK)
hashvalXPrivK := new(big.Int).Add(hashval, xPrivK) hashvalXPrivK := new(big.Int).Add(hashval, xPrivK)
// inv * (hashval + m.X * privK) mod dsa.N // inv * (hashval + m.X * privK) mod dsa.N
a := new(big.Int).Mul(inv, hashvalXPrivK) 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 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) { 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 { if err != nil {
return false, err return false, err
} }
pubKU2, err := dsa.EC.Mul(pubK, int(u2.Int64()))
pubKU2, err := dsa.EC.Mul(pubK, u2)
if err != nil { if err != nil {
return false, err return false, err
} }
@ -66,6 +75,6 @@ func (dsa DSA) Verify(hashval *big.Int, sig [2]*big.Int, pubK ecc.Point) (bool,
if err != nil { if err != nil {
return false, err 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 return bytes.Equal(pXmodN.Bytes(), sig[0].Bytes()), nil
} }

+ 14
- 21
ecdsa/ecdsa_test.go

@ -4,21 +4,20 @@ import (
"math/big" "math/big"
"testing" "testing"
ecc "../ecc"
"github.com/arnaucube/cryptofun/ecc"
"github.com/stretchr/testify/assert"
) )
func TestNewECDSA(t *testing.T) { func TestNewECDSA(t *testing.T) {
ec := ecc.NewEC(1, 18, 19) ec := ecc.NewEC(1, 18, 19)
g := ecc.Point{big.NewInt(int64(7)), big.NewInt(int64(11))} g := ecc.Point{big.NewInt(int64(7)), big.NewInt(int64(11))}
dsa, err := NewDSA(ec, g) 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) 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))}) { if !pubK.Equal(ecc.Point{big.NewInt(int64(13)), big.NewInt(int64(9))}) {
t.Errorf("pubK!=(13, 9)") t.Errorf("pubK!=(13, 9)")
} }
@ -28,24 +27,18 @@ func TestECDSASignAndVerify(t *testing.T) {
ec := ecc.NewEC(1, 18, 19) ec := ecc.NewEC(1, 18, 19)
g := ecc.Point{big.NewInt(int64(7)), big.NewInt(int64(11))} g := ecc.Point{big.NewInt(int64(7)), big.NewInt(int64(11))}
dsa, err := NewDSA(ec, g) 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) pubK, err := dsa.PubK(privK)
if err != nil {
t.Errorf(err.Error())
}
assert.Nil(t, err)
hashval := big.NewInt(int64(40)) hashval := big.NewInt(int64(40))
r := big.NewInt(int64(11)) r := big.NewInt(int64(11))
sig, err := dsa.Sign(hashval, privK, r) 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) verified, err := dsa.Verify(hashval, sig, pubK)
if !verified {
t.Errorf("verified == false")
}
assert.True(t, verified)
} }

ElGamal/elGamal.go → elgamal/elgamal.go

@ -1,14 +1,16 @@
package elgamal package elgamal
import ( import (
ecc "../ecc"
"math/big"
"github.com/arnaucube/cryptofun/ecc"
) )
// EG is the ElGamal data structure // EG is the ElGamal data structure
type EG struct { type EG struct {
EC ecc.EC EC ecc.EC
G ecc.Point G ecc.Point
N int
N *big.Int
} }
// NewEG defines a new EG data structure // NewEG defines a new EG data structure
@ -22,19 +24,22 @@ func NewEG(ec ecc.EC, g ecc.Point) (EG, error) {
} }
// PubK returns the public key Point calculated from the private key over the elliptic curve // 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 // 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 return pubK, err
} }
// Encrypt encrypts a point m with the public key point, returns two points // 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 { if err != nil {
return [2]ecc.Point{}, err 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 { if err != nil {
return [2]ecc.Point{}, err return [2]ecc.Point{}, err
} }
@ -47,10 +52,11 @@ func (eg EG) Encrypt(m ecc.Point, pubK ecc.Point, r int) ([2]ecc.Point, error) {
} }
// Decrypt decrypts c (two points) with the private key, returns the point decrypted // 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] c1 := c[0]
c2 := c[1] 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 { if err != nil {
return ecc.Point{}, err return ecc.Point{}, err
} }

ElGamal/elGamal_test.go → elgamal/elgamal_test.go

@ -4,21 +4,20 @@ import (
"math/big" "math/big"
"testing" "testing"
ecc "../ecc"
"github.com/arnaucube/cryptofun/ecc"
"github.com/stretchr/testify/assert"
) )
func TestNewEG(t *testing.T) { func TestNewEG(t *testing.T) {
ec := ecc.NewEC(1, 18, 19) ec := ecc.NewEC(1, 18, 19)
g := ecc.Point{big.NewInt(int64(7)), big.NewInt(int64(11))} g := ecc.Point{big.NewInt(int64(7)), big.NewInt(int64(11))}
eg, err := NewEG(ec, g) 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) 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))}) { if !pubK.Equal(ecc.Point{big.NewInt(int64(13)), big.NewInt(int64(9))}) {
t.Errorf("pubK!=(13, 9)") t.Errorf("pubK!=(13, 9)")
} }
@ -27,20 +26,17 @@ func TestEGEncrypt(t *testing.T) {
ec := ecc.NewEC(1, 18, 19) ec := ecc.NewEC(1, 18, 19)
g := ecc.Point{big.NewInt(int64(7)), big.NewInt(int64(11))} g := ecc.Point{big.NewInt(int64(7)), big.NewInt(int64(11))}
eg, err := NewEG(ec, g) 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) pubK, err := eg.PubK(privK)
if err != nil {
t.Errorf(err.Error())
}
assert.Nil(t, err)
// m: point to encrypt // m: point to encrypt
m := ecc.Point{big.NewInt(int64(11)), big.NewInt(int64(12))} 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))}) { if !c[0].Equal(ecc.Point{big.NewInt(int64(8)), big.NewInt(int64(5))}) {
t.Errorf("c[0] != (8, 5), encryption failed") t.Errorf("c[0] != (8, 5), encryption failed")
} }
@ -53,24 +49,20 @@ func TestEGDecrypt(t *testing.T) {
ec := ecc.NewEC(1, 18, 19) ec := ecc.NewEC(1, 18, 19)
g := ecc.Point{big.NewInt(int64(7)), big.NewInt(int64(11))} g := ecc.Point{big.NewInt(int64(7)), big.NewInt(int64(11))}
eg, err := NewEG(ec, g) 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) pubK, err := eg.PubK(privK)
if err != nil {
t.Errorf(err.Error())
}
assert.Nil(t, err)
// m: point to encrypt // m: point to encrypt
m := ecc.Point{big.NewInt(int64(11)), big.NewInt(int64(12))} 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) d, err := eg.Decrypt(c, privK)
if err != nil {
t.Errorf(err.Error())
}
assert.Nil(t, err)
if !m.Equal(d) { if !m.Equal(d) {
t.Errorf("m != d, decrypting failed") t.Errorf("m != d, decrypting failed")
} }

+ 7
- 0
go.mod

@ -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
)

+ 6
- 0
go.sum

@ -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=

+ 2
- 1
paillier/paillier.go

@ -5,7 +5,8 @@ import (
"errors" "errors"
"math/big" "math/big"
prime "../prime"
// prime "../prime"
"github.com/arnaucube/cryptofun/prime"
) )
const ( const (

+ 6
- 6
paillier/paillier_test.go

@ -5,13 +5,14 @@ import (
"fmt" "fmt"
"math/big" "math/big"
"testing" "testing"
"github.com/stretchr/testify/assert"
) )
func TestEncryptDecrypt(t *testing.T) { func TestEncryptDecrypt(t *testing.T) {
key, err := GenerateKeyPair() key, err := GenerateKeyPair()
if err != nil {
t.Errorf(err.Error())
}
assert.Nil(t, err)
mBytes := []byte("Hi") mBytes := []byte("Hi")
m := new(big.Int).SetBytes(mBytes) m := new(big.Int).SetBytes(mBytes)
c := Encrypt(m, key.PubK) c := Encrypt(m, key.PubK)
@ -24,9 +25,8 @@ func TestEncryptDecrypt(t *testing.T) {
func TestHomomorphicAddition(t *testing.T) { func TestHomomorphicAddition(t *testing.T) {
key, err := GenerateKeyPair() key, err := GenerateKeyPair()
if err != nil {
t.Errorf(err.Error())
}
assert.Nil(t, err)
n1 := big.NewInt(int64(110)) n1 := big.NewInt(int64(110))
n2 := big.NewInt(int64(150)) n2 := big.NewInt(int64(150))
c1 := Encrypt(n1, key.PubK) c1 := Encrypt(n1, key.PubK)

+ 6
- 9
rsa/rsa_test.go

@ -4,13 +4,14 @@ import (
"bytes" "bytes"
"math/big" "math/big"
"testing" "testing"
"github.com/stretchr/testify/assert"
) )
func TestEncryptDecrypt(t *testing.T) { func TestEncryptDecrypt(t *testing.T) {
key, err := GenerateKeyPair() key, err := GenerateKeyPair()
if err != nil {
t.Errorf(err.Error())
}
assert.Nil(t, err)
mBytes := []byte("Hi") mBytes := []byte("Hi")
m := new(big.Int).SetBytes(mBytes) m := new(big.Int).SetBytes(mBytes)
c := Encrypt(m, key.PubK) c := Encrypt(m, key.PubK)
@ -22,9 +23,7 @@ func TestEncryptDecrypt(t *testing.T) {
} }
func TestBlindSignature(t *testing.T) { func TestBlindSignature(t *testing.T) {
key, err := GenerateKeyPair() key, err := GenerateKeyPair()
if err != nil {
t.Errorf(err.Error())
}
assert.Nil(t, err)
mBytes := []byte("Hi") mBytes := []byte("Hi")
m := new(big.Int).SetBytes(mBytes) m := new(big.Int).SetBytes(mBytes)
@ -46,9 +45,7 @@ func TestBlindSignature(t *testing.T) {
func TestHomomorphicMultiplication(t *testing.T) { func TestHomomorphicMultiplication(t *testing.T) {
key, err := GenerateKeyPair() key, err := GenerateKeyPair()
if err != nil {
t.Errorf(err.Error())
}
assert.Nil(t, err)
n1 := big.NewInt(int64(11)) n1 := big.NewInt(int64(11))
n2 := big.NewInt(int64(15)) n2 := big.NewInt(int64(15))

+ 136
- 0
schnorr/schnorr.go

@ -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
}

+ 65
- 0
schnorr/schnorr_test.go

@ -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)
}

secrets/sercrets.go → shamirsecretsharing/shamirsecretsharing.go

@ -1,4 +1,4 @@
package secrets
package shamirsecretsharing
import ( import (
"crypto/rand" "crypto/rand"
@ -10,11 +10,11 @@ const (
bits = 1024 bits = 1024
) )
// Create calculates the secrets to share from given parameters
// t: number of secrets needed // t: number of secrets needed
// n: number of shares // n: number of shares
// p: random point // p: random point
// k: secret to share // 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) { func Create(t, n, p, k *big.Int) (result [][]*big.Int, err error) {
if k.Cmp(p) > 0 { if k.Cmp(p) > 0 {
return nil, errors.New("Error: need k<p. k: " + k.String() + ", p: " + p.String()) return nil, errors.New("Error: need k<p. k: " + k.String() + ", p: " + p.String())

secrets/secrets_test.go → shamirsecretsharing/shamirsecretsharing_test.go

@ -1,17 +1,17 @@
package secrets
package shamirsecretsharing
import ( import (
"crypto/rand" "crypto/rand"
"math/big" "math/big"
"testing" "testing"
"github.com/stretchr/testify/assert"
) )
func TestCreate(t *testing.T) { func TestCreate(t *testing.T) {
k := 123456789 k := 123456789
p, err := rand.Prime(rand.Reader, bits/2) p, err := rand.Prime(rand.Reader, bits/2)
if err != nil {
t.Errorf(err.Error())
}
assert.Nil(t, err)
nNeededSecrets := big.NewInt(int64(3)) nNeededSecrets := big.NewInt(int64(3))
nShares := big.NewInt(int64(6)) nShares := big.NewInt(int64(6))
@ -20,9 +20,7 @@ func TestCreate(t *testing.T) {
nShares, nShares,
p, p,
big.NewInt(int64(k))) big.NewInt(int64(k)))
if err != nil {
t.Errorf(err.Error())
}
assert.Nil(t, err)
//generate sharesToUse //generate sharesToUse
var sharesToUse [][]*big.Int var sharesToUse [][]*big.Int

Loading…
Cancel
Save