@ -0,0 +1,71 @@ |
|||||
|
package ecdsa |
||||
|
|
||||
|
import ( |
||||
|
"bytes" |
||||
|
"math/big" |
||||
|
|
||||
|
ecc "../ecc" |
||||
|
) |
||||
|
|
||||
|
// DSA is the ECDSA data structure
|
||||
|
type DSA struct { |
||||
|
EC ecc.EC |
||||
|
G ecc.Point |
||||
|
N int |
||||
|
} |
||||
|
|
||||
|
// NewDSA defines a new DSA data structure
|
||||
|
func NewDSA(ec ecc.EC, g ecc.Point) (DSA, error) { |
||||
|
var dsa DSA |
||||
|
var err error |
||||
|
dsa.EC = ec |
||||
|
dsa.G = g |
||||
|
dsa.N, err = ec.Order(g) |
||||
|
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) { |
||||
|
// privK: rand < ec.Q
|
||||
|
pubK, err := dsa.EC.Mul(dsa.G, privK) |
||||
|
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())) |
||||
|
if err != nil { |
||||
|
return [2]*big.Int{}, err |
||||
|
} |
||||
|
// inv(r) mod dsa.N
|
||||
|
inv := new(big.Int).ModInverse(r, big.NewInt(int64(dsa.N))) |
||||
|
// m.X * privK
|
||||
|
xPrivK := new(big.Int).Mul(m.X, big.NewInt(int64(privK))) |
||||
|
// (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))) |
||||
|
return [2]*big.Int{m.X, r2}, err |
||||
|
} |
||||
|
|
||||
|
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))) |
||||
|
|
||||
|
gU1, err := dsa.EC.Mul(dsa.G, int(u1.Int64())) |
||||
|
if err != nil { |
||||
|
return false, err |
||||
|
} |
||||
|
pubKU2, err := dsa.EC.Mul(pubK, int(u2.Int64())) |
||||
|
if err != nil { |
||||
|
return false, err |
||||
|
} |
||||
|
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))) |
||||
|
return bytes.Equal(pXmodN.Bytes(), sig[0].Bytes()), nil |
||||
|
} |
@ -0,0 +1,51 @@ |
|||||
|
package ecdsa |
||||
|
|
||||
|
import ( |
||||
|
"math/big" |
||||
|
"testing" |
||||
|
|
||||
|
ecc "../ecc" |
||||
|
) |
||||
|
|
||||
|
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 |
||||
|
pubK, err := dsa.PubK(privK) |
||||
|
if err != nil { |
||||
|
t.Errorf(err.Error()) |
||||
|
} |
||||
|
if !pubK.Equal(ecc.Point{big.NewInt(int64(13)), big.NewInt(int64(9))}) { |
||||
|
t.Errorf("pubK!=(13, 9)") |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
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 |
||||
|
pubK, err := dsa.PubK(privK) |
||||
|
if err != nil { |
||||
|
t.Errorf(err.Error()) |
||||
|
} |
||||
|
hashval := big.NewInt(int64(40)) |
||||
|
r := big.NewInt(int64(11)) |
||||
|
|
||||
|
sig, err := dsa.Sign(hashval, privK, r) |
||||
|
if err != nil { |
||||
|
t.Errorf(err.Error()) |
||||
|
} |
||||
|
|
||||
|
verified, err := dsa.Verify(hashval, sig, pubK) |
||||
|
if !verified { |
||||
|
t.Errorf("verified == false") |
||||
|
} |
||||
|
} |