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 }