mirror of
https://github.com/arnaucube/cryptofun.git
synced 2026-02-28 05:16:46 +01:00
Schnorr signature implemented. ECC point multiplication with big int. Refactor of the code.
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1 +1,2 @@
|
||||
fmt
|
||||
schnorr.goBACKUP
|
||||
|
||||
@@ -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 @@ https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm
|
||||
- [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 @@ const (
|
||||
|
||||
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)
|
||||
|
||||
42
ecc/ecc.go
42
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)}
|
||||
}
|
||||
|
||||
// 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 @@ func (ec *EC) Add(p1, p2 Point) (Point, error) {
|
||||
}
|
||||
|
||||
// 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")
|
||||
}
|
||||
|
||||
200
ecc/ecc_test.go
200
ecc/ecc_test.go
@@ -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 TestECC(t *testing.T) {
|
||||
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 @@ func TestAddSamePoint(t *testing.T) {
|
||||
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 TestMulPoint1(t *testing.T) {
|
||||
ec := NewEC(0, 7, 29)
|
||||
p := Point{big.NewInt(int64(11)), big.NewInt(int64(27))}
|
||||
|
||||
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)")
|
||||
}
|
||||
|
||||
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(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)")
|
||||
}
|
||||
|
||||
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 TestMulPoint2(t *testing.T) {
|
||||
ec := NewEC(0, 7, 29)
|
||||
p1 := Point{big.NewInt(int64(4)), big.NewInt(int64(19))}
|
||||
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.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))}) {
|
||||
t.Errorf(q7.String() + " == q7 != (19, 14)")
|
||||
}
|
||||
|
||||
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)")
|
||||
}
|
||||
|
||||
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))}
|
||||
|
||||
p1p1, err := ec.Add(p1, p1)
|
||||
if err != nil {
|
||||
t.Errorf(err.Error())
|
||||
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)")
|
||||
}
|
||||
p1p1, err = ec.Add(p1p1, p1)
|
||||
if err != nil {
|
||||
t.Errorf(err.Error())
|
||||
if !q.Equal(p1_3) {
|
||||
t.Errorf("p*3 == " + q.String() + ", p+p+p == " + p1_3.String())
|
||||
}
|
||||
q, err := ec.Mul(p1, 3)
|
||||
if err != nil {
|
||||
t.Errorf(err.Error())
|
||||
|
||||
// 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(p1p1) {
|
||||
fmt.Println(q)
|
||||
fmt.Println(p1p1)
|
||||
t.Errorf("q!=p1*p1")
|
||||
if !q.Equal(p1_4) {
|
||||
t.Errorf("p*4 == " + q.String() + ", p+p+p+p == " + p1_4.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestMul(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())
|
||||
}
|
||||
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())
|
||||
}
|
||||
if !q7.Equal(Point{big.NewInt(int64(19)), big.NewInt(int64(14))}) {
|
||||
t.Errorf("q7!=(19, 14)")
|
||||
}
|
||||
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))
|
||||
|
||||
q8, err := ec.Mul(p1, 8)
|
||||
if err != nil {
|
||||
t.Errorf(err.Error())
|
||||
}
|
||||
if !q8.Equal(Point{big.NewInt(int64(19)), big.NewInt(int64(15))}) {
|
||||
t.Errorf("q8!=(19, 15)")
|
||||
}
|
||||
// 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 @@ import (
|
||||
|
||||
var (
|
||||
bigZero = big.NewInt(int64(0))
|
||||
bigOne = big.NewInt(int64(1))
|
||||
zeroPoint = Point{bigZero, bigZero}
|
||||
)
|
||||
|
||||
@@ -26,3 +27,8 @@ func (c1 *Point) Equal(c2 Point) bool {
|
||||
}
|
||||
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 @@ 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
|
||||
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 @@ func (dsa DSA) Verify(hashval *big.Int, sig [2]*big.Int, pubK ecc.Point) (bool,
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -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 @@ 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
|
||||
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 @@ 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
|
||||
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")
|
||||
}
|
||||
7
go.mod
Normal file
7
go.mod
Normal file
@@ -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
go.sum
Normal file
6
go.sum
Normal file
@@ -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 @@ import (
|
||||
"errors"
|
||||
"math/big"
|
||||
|
||||
prime "../prime"
|
||||
// prime "../prime"
|
||||
"github.com/arnaucube/cryptofun/prime"
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
@@ -5,13 +5,14 @@ import (
|
||||
"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 TestEncryptDecrypt(t *testing.T) {
|
||||
|
||||
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 TestEncryptDecrypt(t *testing.T) {
|
||||
}
|
||||
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 TestBlindSignature(t *testing.T) {
|
||||
|
||||
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))
|
||||
|
||||
136
schnorr/schnorr.go
Normal file
136
schnorr/schnorr.go
Normal file
@@ -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
schnorr/schnorr_test.go
Normal file
65
schnorr/schnorr_test.go
Normal file
@@ -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,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())
|
||||
@@ -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 @@ func TestCreate(t *testing.T) {
|
||||
nShares,
|
||||
p,
|
||||
big.NewInt(int64(k)))
|
||||
if err != nil {
|
||||
t.Errorf(err.Error())
|
||||
}
|
||||
assert.Nil(t, err)
|
||||
|
||||
//generate sharesToUse
|
||||
var sharesToUse [][]*big.Int
|
||||
Reference in New Issue
Block a user