From 77c02f36ee4249a53664f63d22f32311bb7fb9d2 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Mon, 19 May 2014 23:21:39 -0500 Subject: [PATCH] Cleanup new code introduced by Pull Request #4. - Keep comments to 80 cols for consistency with the rest of the code base - Made verify a method off of Signature instead of PublicKey since one verifies a signature with a public key as opposed to the other way around - Return new signature from Sign function directly rather than creating a local temporary variable - Modify a couple of comments as recommended by @owainga - Update sample usage in doc.go for both signing messages and verifying signatures ok @owainga --- doc.go | 78 ++++++++++++++++++++++++++++++++++++++++++++--- privkey.go | 15 ++++----- pubkey.go | 6 ---- pubkey_test.go | 2 +- signature.go | 6 ++++ test_coverage.txt | 13 ++++---- 6 files changed, 93 insertions(+), 27 deletions(-) diff --git a/doc.go b/doc.go index fdad2997..90f2b90e 100644 --- a/doc.go +++ b/doc.go @@ -20,15 +20,83 @@ some initial work by ThePiachu. Usage -To verify a secp256k1 signature the following may be done: +To verify a secp256k1 signature, the following may be done: - import crypto/ecdsa + package main - pubKey, err := btcec.ParsePubKey(pkStr, btcec.S256()) + import ( + "encoding/hex" + "github.com/conformal/btcec" + "github.com/conformal/btcwire" + "log" + ) - signature, err := btcec.ParseSignature(sigStr, btcec.S256()) + func main() { + // Decode hex-encoded serialized public key. + pubKeyBytes, err := hex.DecodeString("02a673638cb9587cb68ea08dbef685c"+ + "6f2d2a751a8b3c6f2a7e9a4999e6e4bfaf5") + if err != nil { + log.Fatal(err) + } + pubKey, err := btcec.ParsePubKey(pubKeyBytes, btcec.S256()) + if err != nil { + log.Fatal(err) + } - ok := ecdsa.Verify(pubKey, message, signature.R, signature.S) + // Decode hex-encoded serialized signature. + sigBytes, err := hex.DecodeString("30450220090ebfb3690a0ff115bb1b38b"+ + "8b323a667b7653454f1bccb06d4bbdca42c2079022100ec95778b51e707"+ + "1cb1205f8bde9af6592fc978b0452dafe599481c46d6b2e479") + if err != nil { + log.Fatal(err) + } + decodedSig, err := btcec.ParseSignature(sigBytes, btcec.S256()) + if err != nil { + log.Fatal(err) + } + // Verify the signature for the message using the public key. + message := "test message" + messageHash := btcwire.DoubleSha256([]byte(message)) + if decodedSig.Verify(messageHash, pubKey) { + log.Println("Signature Verified") + } + } + +To sign a message using a secp256k1 private key, the following may be done: + + package main + + import ( + "encoding/hex" + "github.com/conformal/btcec" + "github.com/conformal/btcwire" + "log" + ) + + func main() { + // Decode a hex-encoded private key. + pkBytes, err := hex.DecodeString("22a47fa09a223f2aa079edf85a7c2d4f87"+ + "20ee63e502ee2869afab7de234b80c") + if err != nil { + log.Fatal(err) + } + priv, pub := btcec.PrivKeyFromBytes(btcec.S256(), pkBytes) + + // Sign a message using the private key. + message := "test message" + messageHash := btcwire.DoubleSha256([]byte(message)) + sig, err := priv.Sign(messageHash) + if err != nil { + log.Fatal(err) + } + + log.Printf("Serialized Signature: %x\n", sig.Serialize()) + + // Verify the signature for the message using the public key. + if sig.Verify(messageHash, pub) { + log.Println("Signature Verified") + } + } */ package btcec diff --git a/privkey.go b/privkey.go index ad1dfc1f..5e9d15df 100644 --- a/privkey.go +++ b/privkey.go @@ -10,8 +10,9 @@ import ( "math/big" ) -// PrivateKey is an ecdsa.PrivateKey -// It provides a method Sign +// PrivateKey wraps an ecdsa.PrivateKey as a convenience mainly for signing +// things with the the private key without having to directly import the ecdsa +// package. type PrivateKey ecdsa.PrivateKey // PrivKeyFromBytes returns a private and public key for `curve' based on the @@ -37,16 +38,12 @@ 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). +// Sign wraps ecdsa.Sign to sign the provided hash (which should be the result +// of hashing a larger message) using the private key. 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 + return &Signature{R: r, S: s}, nil } diff --git a/pubkey.go b/pubkey.go index 0d7d679d..cf0da666 100644 --- a/pubkey.go +++ b/pubkey.go @@ -162,9 +162,3 @@ 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) -} diff --git a/pubkey_test.go b/pubkey_test.go index f0599dc3..24234669 100644 --- a/pubkey_test.go +++ b/pubkey_test.go @@ -235,7 +235,7 @@ func TestPrivKeys(t *testing.T) { continue } - if !pub.Verify(hash, sig) { + if !sig.Verify(hash, pub) { t.Errorf("%s could not verify: %v", test.name, err) continue } diff --git a/signature.go b/signature.go index e9da0dc4..6826363d 100644 --- a/signature.go +++ b/signature.go @@ -54,6 +54,12 @@ func (sig *Signature) Serialize() []byte { return b } +// Verify calls ecdsa.Verify to verify the signature of hash using the public +// key. It returns true if the signature is valid, false otherwise. +func (sig *Signature) Verify(hash []byte, pubKey *PublicKey) bool { + return ecdsa.Verify(pubKey.ToECDSA(), hash, sig.R, sig.S) +} + func parseSig(sigStr []byte, curve elliptic.Curve, der bool) (*Signature, error) { // Originally this code used encoding/asn1 in order to parse the // signature, but a number of problems were found with this approach. diff --git a/test_coverage.txt b/test_coverage.txt index f621cfa3..8a01cb6f 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -54,16 +54,17 @@ github.com/conformal/btcec/field.go fieldVal.Mul 100.00% (1/1) github.com/conformal/btcec/field.go fieldVal.Square 100.00% (1/1) github.com/conformal/btcec/privkey.go PrivateKey.ToECDSA 100.00% (1/1) github.com/conformal/btcec/pubkey.go isOdd 100.00% (1/1) -github.com/conformal/btcec/pubkey.go PublicKey.ToECDSA 100.00% (1/1) -github.com/conformal/btcec/pubkey.go PublicKey.Verify 100.00% (1/1) +github.com/conformal/btcec/signature.go Signature.Verify 100.00% (1/1) github.com/conformal/btcec/signature.go ParseSignature 100.00% (1/1) github.com/conformal/btcec/signature.go ParseDERSignature 100.00% (1/1) +github.com/conformal/btcec/pubkey.go PublicKey.ToECDSA 100.00% (1/1) github.com/conformal/btcec/pubkey.go ParsePubKey 92.86% (26/28) +github.com/conformal/btcec/signature.go SignCompact 90.91% (20/22) github.com/conformal/btcec/pubkey.go decompressPoint 88.89% (8/9) github.com/conformal/btcec/signature.go recoverKeyFromSignature 86.96% (20/23) -github.com/conformal/btcec/signature.go SignCompact 81.82% (18/22) -github.com/conformal/btcec/privkey.go PrivateKey.Sign 80.00% (4/5) -github.com/conformal/btcec/signature.go hashToInt 77.78% (7/9) github.com/conformal/btcec/signature.go RecoverCompact 77.78% (7/9) -github.com/conformal/btcec ------------------------------------- 98.37% (907/922) +github.com/conformal/btcec/signature.go hashToInt 77.78% (7/9) +github.com/conformal/btcec/privkey.go PrivateKey.Sign 75.00% (3/4) +github.com/conformal/btcec/pubkey.go PublicKey.Verify 0.00% (0/1) +github.com/conformal/btcec ------------------------------------- 98.48% (908/922)