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