diff --git a/privkey.go b/privkey.go index 8631f222..ad1dfc1f 100644 --- a/privkey.go +++ b/privkey.go @@ -6,12 +6,17 @@ package btcec import ( "crypto/ecdsa" + "crypto/rand" "math/big" ) +// PrivateKey is an ecdsa.PrivateKey +// It provides a method Sign +type PrivateKey ecdsa.PrivateKey + // PrivKeyFromBytes returns a private and public key for `curve' based on the // private key passed as an argument as a byte slice. -func PrivKeyFromBytes(curve *KoblitzCurve, pk []byte) (*ecdsa.PrivateKey, +func PrivKeyFromBytes(curve *KoblitzCurve, pk []byte) (*PrivateKey, *PublicKey) { x, y := curve.ScalarBaseMult(pk) @@ -24,5 +29,24 @@ func PrivKeyFromBytes(curve *KoblitzCurve, pk []byte) (*ecdsa.PrivateKey, D: new(big.Int).SetBytes(pk), } - return priv, (*PublicKey)(&priv.PublicKey) + return (*PrivateKey)(priv), (*PublicKey)(&priv.PublicKey) +} + +// ToECDSA returns the private key as a *ecdsa.PrivateKey. +func (p *PrivateKey) ToECDSA() *ecdsa.PrivateKey { + return (*ecdsa.PrivateKey)(p) +} + +// Sign wraps ecdsa.Sign to sign an arbitrary length hash (which should be the result of hashing a larger message) using the private key. +// It returns the signature as a *Signature. The security of the private key depends on the entropy of rand (crypto/rand.Reader). +func (p *PrivateKey) Sign(hash []byte) (*Signature, error) { + r, s, err := ecdsa.Sign(rand.Reader, p.ToECDSA(), hash) + if err != nil { + return nil, err + } + sig := &Signature{ + R: r, + S: s, + } + return sig, nil } diff --git a/pubkey.go b/pubkey.go index cf0da666..0d7d679d 100644 --- a/pubkey.go +++ b/pubkey.go @@ -162,3 +162,9 @@ func paddedAppend(size uint, dst, src []byte) []byte { } return append(dst, src...) } + +// Verify calls ecdsa.Verify to verify the signature of hash using the public key. +// Its return value records whether the signature is valid. +func (p *PublicKey) Verify(hash []byte, sig *Signature) bool { + return ecdsa.Verify(p.ToECDSA(), hash, sig.R, sig.S) +}