package ecdsa
|
|
|
|
import (
|
|
"bytes"
|
|
"math/big"
|
|
|
|
// ecc "../ecc"
|
|
"github.com/arnaucube/cryptofun/ecc"
|
|
)
|
|
|
|
// DSA is the ECDSA data structure
|
|
type DSA struct {
|
|
EC ecc.EC
|
|
G ecc.Point
|
|
N *big.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 *big.Int) (ecc.Point, error) {
|
|
// privK: rand < ec.Q
|
|
privKCopy := new(big.Int).SetBytes(privK.Bytes())
|
|
pubK, err := dsa.EC.Mul(dsa.G, privKCopy)
|
|
return pubK, err
|
|
}
|
|
|
|
// 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, dsa.N)
|
|
// m.X * 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, 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], 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, u1)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
pubKU2, err := dsa.EC.Mul(pubK, u2)
|
|
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, dsa.N)
|
|
return bytes.Equal(pXmodN.Bytes(), sig[0].Bytes()), nil
|
|
}
|