From 21f0d57fe42b657350976810459f17ab2669e370 Mon Sep 17 00:00:00 2001 From: arnaucube Date: Sat, 6 Apr 2019 21:22:31 +0200 Subject: [PATCH] add core/keys: NewKey, key parsing, sign and verify --- core/keys.go | 94 +++++++++++++++++++++++++++++++++++++++++++++++ core/keys_test.go | 34 +++++++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 core/keys.go create mode 100644 core/keys_test.go diff --git a/core/keys.go b/core/keys.go new file mode 100644 index 0000000..6883d12 --- /dev/null +++ b/core/keys.go @@ -0,0 +1,94 @@ +package core + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "encoding/hex" + "errors" + "math/big" +) + +// Address is the type data for addresses +type Address [32]byte + +func (addr Address) String() string { + return hex.EncodeToString(addr[:]) +} + +func NewKey() (*ecdsa.PrivateKey, error) { + curve := elliptic.P256() + + privatekey := new(ecdsa.PrivateKey) + privatekey, err := ecdsa.GenerateKey(curve, rand.Reader) + if err != nil { + return nil, err + } + + return privatekey, err +} + +func PackPubK(pubK *ecdsa.PublicKey) []byte { + return elliptic.Marshal(pubK.Curve, pubK.X, pubK.Y) +} +func UnpackPubK(b []byte) *ecdsa.PublicKey { + x, y := elliptic.Unmarshal(elliptic.P256(), b) + return &ecdsa.PublicKey{ + Curve: elliptic.P256(), + X: x, + Y: y, + } +} + +func AddressFromPrivK(privK *ecdsa.PrivateKey) Address { + h := HashBytes(PackPubK(&privK.PublicKey)) + return Address(h) +} + +func PackSignature(r, s *big.Int) []byte { + sig := r.Bytes() + sig = append(sig, s.Bytes()...) + return sig +} + +func UnpackSignature(sig []byte) (*big.Int, *big.Int, error) { + if len(sig) != 64 { + return nil, nil, errors.New("Invalid signature") + } + rBytes := sig[:32] + sBytes := sig[32:] + + r := new(big.Int).SetBytes(rBytes) + s := new(big.Int).SetBytes(sBytes) + + return r, s, nil +} + +func Sign(privK *ecdsa.PrivateKey, m []byte) ([]byte, error) { + r := big.NewInt(0) + s := big.NewInt(0) + + hashMsg := HashBytes(m) + + r, s, err := ecdsa.Sign(rand.Reader, privK, hashMsg[:]) + if err != nil { + return []byte{}, err + } + + sig := PackSignature(r, s) + + return sig, nil + +} + +func VerifySignature(pubK *ecdsa.PublicKey, m []byte, sig []byte) bool { + hashMsg := HashBytes(m) + + r, s, err := UnpackSignature(sig) + if err != nil { + return false + } + + verified := ecdsa.Verify(pubK, hashMsg[:], r, s) + return verified +} diff --git a/core/keys_test.go b/core/keys_test.go new file mode 100644 index 0000000..e577576 --- /dev/null +++ b/core/keys_test.go @@ -0,0 +1,34 @@ +package core + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestNewKey(t *testing.T) { + _, err := NewKey() + assert.Nil(t, err) +} +func TestAddress(t *testing.T) { + privK, err := NewKey() + assert.Nil(t, err) + + addr := AddressFromPrivK(privK) + fmt.Println(addr.String()) +} + +func TestSignAndVerify(t *testing.T) { + privK, err := NewKey() + assert.Nil(t, err) + + // Sign + m := []byte("test") + sig, err := Sign(privK, m) + assert.Nil(t, err) + + // Verify + verified := VerifySignature(&privK.PublicKey, m, sig) + assert.True(t, verified) +}