Skip to content

Commit

Permalink
build(deps): bump btcd in v0.46 (#14846)
Browse files Browse the repository at this point in the history
Co-authored-by: yihuang <huang@crypto.com>
Co-authored-by: Julien Robert <julien@rbrt.fr>
Co-authored-by: Elias Naur <103319121+elias-orijtech@users.noreply.github.com>
Co-authored-by: Marko <marbar3778@yahoo.com>
  • Loading branch information
5 people committed Feb 7, 2023
1 parent 82138c9 commit 0b64514
Show file tree
Hide file tree
Showing 14 changed files with 91 additions and 103 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,11 @@ Ref: https://keepachangelog.com/en/1.0.0/

## [Unreleased]

## [v0.46.9](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.46.9) - 2022-02-06
## [v0.46.9](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.46.9) - 2022-02-07

### Improvements

* (deps) [#14846](https://github.com/cosmos/cosmos-sdk/pull/14846) Bump btcd.
* (deps) Bump Tendermint version to [v0.34.26](https://github.com/informalsystems/tendermint/releases/tag/v0.34.26).
* (store) [#14189](https://github.com/cosmos/cosmos-sdk/pull/14189) Add config `iavl-lazy-loading` to enable lazy loading of iavl store, to improve start up time of archive nodes, add method `SetLazyLoading` to `CommitMultiStore` interface.
* A new field has been added to the app.toml. This alllows nodes with larger databases to startup quicker
Expand Down
4 changes: 2 additions & 2 deletions crypto/hd/hdpath.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
"strconv"
"strings"

"github.com/btcsuite/btcd/btcec"
"github.com/btcsuite/btcd/btcec/v2"
)

// NewParams creates a BIP 44 parameter object from the params:
Expand Down Expand Up @@ -225,7 +225,7 @@ func derivePrivateKey(privKeyBytes [32]byte, chainCode [32]byte, index uint32, h
data = append([]byte{byte(0)}, privKeyBytes[:]...)
} else {
// this can't return an error:
_, ecPub := btcec.PrivKeyFromBytes(btcec.S256(), privKeyBytes[:])
_, ecPub := btcec.PrivKeyFromBytes(privKeyBytes[:])
pubkeyBytes := ecPub.SerializeCompressed()
data = pubkeyBytes

Expand Down
4 changes: 2 additions & 2 deletions crypto/keys/secp256k1/secp256k1.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"io"
"math/big"

secp256k1 "github.com/btcsuite/btcd/btcec"
secp256k1 "github.com/btcsuite/btcd/btcec/v2"
"github.com/tendermint/tendermint/crypto"
"golang.org/x/crypto/ripemd160" // nolint: staticcheck // necessary for Bitcoin address format

Expand Down Expand Up @@ -37,7 +37,7 @@ func (privKey *PrivKey) Bytes() []byte {
// PubKey performs the point-scalar multiplication from the privKey on the
// generator point to get the pubkey.
func (privKey *PrivKey) PubKey() cryptotypes.PubKey {
_, pubkeyObject := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKey.Key)
_, pubkeyObject := secp256k1.PrivKeyFromBytes(privKey.Key)
pk := pubkeyObject.SerializeCompressed()
return &PubKey{Key: pk}
}
Expand Down
2 changes: 1 addition & 1 deletion crypto/keys/secp256k1/secp256k1_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"math/big"
"testing"

btcSecp256k1 "github.com/btcsuite/btcd/btcec"
btcSecp256k1 "github.com/btcsuite/btcd/btcec/v2"
"github.com/stretchr/testify/require"
)

Expand Down
52 changes: 20 additions & 32 deletions crypto/keys/secp256k1/secp256k1_nocgo.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,22 @@
package secp256k1

import (
"math/big"

secp256k1 "github.com/btcsuite/btcd/btcec"
secp256k1 "github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/btcec/v2/ecdsa"

"github.com/tendermint/tendermint/crypto"
)

// used to reject malleable signatures
// see:
// - https://github.com/ethereum/go-ethereum/blob/f9401ae011ddf7f8d2d95020b7446c17f8d98dc1/crypto/signature_nocgo.go#L90-L93
// - https://github.com/ethereum/go-ethereum/blob/f9401ae011ddf7f8d2d95020b7446c17f8d98dc1/crypto/crypto.go#L39
var secp256k1halfN = new(big.Int).Rsh(secp256k1.S256().N, 1)

// Sign creates an ECDSA signature on curve Secp256k1, using SHA256 on the msg.
// The returned signature will be of the form R || S (in lower-S form).
func (privKey *PrivKey) Sign(msg []byte) ([]byte, error) {
priv, _ := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKey.Key)
sig, err := priv.Sign(crypto.Sha256(msg))
priv, _ := secp256k1.PrivKeyFromBytes(privKey.Key)
sig, err := ecdsa.SignCompact(priv, crypto.Sha256(msg), false)
if err != nil {
return nil, err
}
sigBytes := serializeSig(sig)
return sigBytes, nil
// remove the first byte which is compactSigRecoveryCode
return sig[1:], nil
}

// VerifyBytes verifies a signature of the form R || S.
Expand All @@ -35,37 +28,32 @@ func (pubKey *PubKey) VerifySignature(msg []byte, sigStr []byte) bool {
if len(sigStr) != 64 {
return false
}
pub, err := secp256k1.ParsePubKey(pubKey.Key, secp256k1.S256())
pub, err := secp256k1.ParsePubKey(pubKey.Key)
if err != nil {
return false
}
// parse the signature:
signature := signatureFromBytes(sigStr)
// Reject malleable signatures. libsecp256k1 does this check but btcec doesn't.
// see: https://github.com/ethereum/go-ethereum/blob/f9401ae011ddf7f8d2d95020b7446c17f8d98dc1/crypto/signature_nocgo.go#L90-L93
if signature.S.Cmp(secp256k1halfN) > 0 {
// Serialize() would negate S value if it is over half order.
// Hence, if the signature is different after Serialize() if should be rejected.
modifiedSignature, parseErr := ecdsa.ParseDERSignature(signature.Serialize())
if parseErr != nil {
return false
}
if !signature.IsEqual(modifiedSignature) {
return false
}
return signature.Verify(crypto.Sha256(msg), pub)
}

// Read Signature struct from R || S. Caller needs to ensure
// that len(sigStr) == 64.
func signatureFromBytes(sigStr []byte) *secp256k1.Signature {
return &secp256k1.Signature{
R: new(big.Int).SetBytes(sigStr[:32]),
S: new(big.Int).SetBytes(sigStr[32:64]),
}
}

// Serialize signature to R || S.
// R, S are padded to 32 bytes respectively.
func serializeSig(sig *secp256k1.Signature) []byte {
rBytes := sig.R.Bytes()
sBytes := sig.S.Bytes()
sigBytes := make([]byte, 64)
// 0 pad the byte arrays from the left if they aren't big enough.
copy(sigBytes[32-len(rBytes):32], rBytes)
copy(sigBytes[64-len(sBytes):64], sBytes)
return sigBytes
func signatureFromBytes(sigStr []byte) *ecdsa.Signature {
var r secp256k1.ModNScalar
r.SetByteSlice(sigStr[:32])
var s secp256k1.ModNScalar
s.SetByteSlice(sigStr[32:64])
return ecdsa.NewSignature(&r, &s)
}
23 changes: 16 additions & 7 deletions crypto/keys/secp256k1/secp256k1_nocgo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ package secp256k1
import (
"testing"

secp256k1 "github.com/btcsuite/btcd/btcec"
secp256k1 "github.com/btcsuite/btcd/btcec/v2"
"github.com/stretchr/testify/require"
)

Expand All @@ -19,20 +19,29 @@ func TestSignatureVerificationAndRejectUpperS(t *testing.T) {
priv := GenPrivKey()
sigStr, err := priv.Sign(msg)
require.NoError(t, err)
sig := signatureFromBytes(sigStr)
require.False(t, sig.S.Cmp(secp256k1halfN) > 0)
var r secp256k1.ModNScalar
r.SetByteSlice(sigStr[:32])
var s secp256k1.ModNScalar
s.SetByteSlice(sigStr[32:64])
require.False(t, s.IsOverHalfOrder())

pub := priv.PubKey()
require.True(t, pub.VerifySignature(msg, sigStr))

// malleate:
sig.S.Sub(secp256k1.S256().CurveParams.N, sig.S)
require.True(t, sig.S.Cmp(secp256k1halfN) > 0)
malSigStr := serializeSig(sig)
var S256 secp256k1.ModNScalar
S256.SetByteSlice(secp256k1.S256().N.Bytes())
s.Negate().Add(&S256)
require.True(t, s.IsOverHalfOrder())

rBytes := r.Bytes()
sBytes := s.Bytes()
malSigStr := make([]byte, 64)
copy(malSigStr[32-len(rBytes):32], rBytes[:])
copy(malSigStr[64-len(sBytes):64], sBytes[:])
require.False(t, pub.VerifySignature(msg, malSigStr),
"VerifyBytes incorrect with malleated & invalid S. sig=%v, key=%v",
sig,
malSigStr,
priv,
)
}
Expand Down
13 changes: 8 additions & 5 deletions crypto/keys/secp256k1/secp256k1_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import (
"math/big"
"testing"

btcSecp256k1 "github.com/btcsuite/btcd/btcec"
btcSecp256k1 "github.com/btcsuite/btcd/btcec/v2"
btcecdsa "github.com/btcsuite/btcd/btcec/v2/ecdsa"
"github.com/cosmos/btcutil/base58"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -64,7 +65,7 @@ func TestSignAndValidateSecp256k1(t *testing.T) {
// ----
// Test cross packages verification
msgHash := crypto.Sha256(msg)
btcPrivKey, btcPubKey := btcSecp256k1.PrivKeyFromBytes(btcSecp256k1.S256(), privKey.Key)
btcPrivKey, btcPubKey := btcSecp256k1.PrivKeyFromBytes(privKey.Key)
// This fails: malformed signature: no header magic
// btcSig, err := secp256k1.ParseSignature(sig, secp256k1.S256())
// require.NoError(t, err)
Expand All @@ -77,9 +78,11 @@ func TestSignAndValidateSecp256k1(t *testing.T) {
ok := ecdsa.Verify(btcPubKey.ToECDSA(), msgHash, r, s)
require.True(t, ok)

sig2, err := btcPrivKey.Sign(msgHash)
sig2, err := btcecdsa.SignCompact(btcPrivKey, msgHash, false)
// Chop off compactSigRecoveryCode.
sig2 = sig2[1:]
require.NoError(t, err)
pubKey.VerifySignature(msg, sig2.Serialize())
pubKey.VerifySignature(msg, sig2)

// ----
// Mutate the signature, just one bit.
Expand All @@ -98,7 +101,7 @@ func TestSecp256k1LoadPrivkeyAndSerializeIsIdentity(t *testing.T) {

// This function creates a private and public key in the underlying libraries format.
// The private key is basically calling new(big.Int).SetBytes(pk), which removes leading zero bytes
priv, _ := btcSecp256k1.PrivKeyFromBytes(btcSecp256k1.S256(), privKeyBytes[:])
priv, _ := btcSecp256k1.PrivKeyFromBytes(privKeyBytes[:])
// this takes the bytes returned by `(big int).Bytes()`, and if the length is less than 32 bytes,
// pads the bytes from the left with zero bytes. Therefore these two functions composed
// result in the identity function on privKeyBytes, hence the following equality check
Expand Down
13 changes: 0 additions & 13 deletions crypto/keys/utils.go

This file was deleted.

17 changes: 7 additions & 10 deletions crypto/ledger/ledger_mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
package ledger

import (
"errors"
"fmt"

"github.com/btcsuite/btcd/btcec"
"github.com/pkg/errors"

"github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/btcec/v2/ecdsa"
"github.com/cosmos/go-bip39"
"github.com/tendermint/tendermint/crypto"

Expand Down Expand Up @@ -56,7 +56,7 @@ func (mock LedgerSECP256K1Mock) GetPublicKeySECP256K1(derivationPath []uint32) (
return nil, err
}

_, pubkeyObject := btcec.PrivKeyFromBytes(btcec.S256(), derivedPriv)
_, pubkeyObject := btcec.PrivKeyFromBytes(derivedPriv)

return pubkeyObject.SerializeUncompressed(), nil
}
Expand All @@ -70,7 +70,7 @@ func (mock LedgerSECP256K1Mock) GetAddressPubKeySECP256K1(derivationPath []uint3
}

// re-serialize in the 33-byte compressed format
cmp, err := btcec.ParsePubKey(pk, btcec.S256())
cmp, err := btcec.ParsePubKey(pk)
if err != nil {
return nil, "", fmt.Errorf("error parsing public key: %v", err)
}
Expand All @@ -97,11 +97,8 @@ func (mock LedgerSECP256K1Mock) SignSECP256K1(derivationPath []uint32, message [
return nil, err
}

priv, _ := btcec.PrivKeyFromBytes(btcec.S256(), derivedPriv)
sig, err := priv.Sign(crypto.Sha256(message))
if err != nil {
return nil, err
}
priv, _ := btcec.PrivKeyFromBytes(derivedPriv)
sig := ecdsa.Sign(priv, crypto.Sha256(message))

return sig.Serialize(), nil
}
Expand Down
2 changes: 1 addition & 1 deletion crypto/ledger/ledger_notavail.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
package ledger

import (
"github.com/pkg/errors"
"errors"
)

// If ledger support (build tag) has been enabled, which implies a CGO dependency,
Expand Down
35 changes: 20 additions & 15 deletions crypto/ledger/ledger_secp256k1.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
package ledger

import (
"errors"
"fmt"
"math/big"
"os"

"github.com/btcsuite/btcd/btcec"
"github.com/pkg/errors"
"github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/btcec/v2/ecdsa"

"github.com/cosmos/cosmos-sdk/crypto/hd"
"github.com/cosmos/cosmos-sdk/crypto/keys"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
"github.com/cosmos/cosmos-sdk/crypto/types"
)
Expand Down Expand Up @@ -169,24 +169,29 @@ func warnIfErrors(f func() error) {
}

func convertDERtoBER(signatureDER []byte) ([]byte, error) {
sigDER, err := btcec.ParseDERSignature(signatureDER, btcec.S256())
sigDER, err := ecdsa.ParseDERSignature(signatureDER)
if err != nil {
return nil, err
}

sigStr := sigDER.Serialize()
// The format of a DER encoded signature is as follows:
// 0x30 <total length> 0x02 <length of R> <R> 0x02 <length of S> <S>
r, s := new(big.Int), new(big.Int)
r.SetBytes(sigStr[4 : 4+sigStr[3]])
s.SetBytes(sigStr[4+sigStr[3]+2:])

sModNScalar := new(btcec.ModNScalar)
sModNScalar.SetByteSlice(s.Bytes())
// based on https://github.com/tendermint/btcd/blob/ec996c5/btcec/signature.go#L33-L50
// low 'S' malleability breaker
sigS := sigDER.S
if keys.IsOverHalfOrder(sigS) {
sigS = new(big.Int).Sub(btcec.S256().N, sigS)
if sModNScalar.IsOverHalfOrder() {
s = new(big.Int).Sub(btcec.S256().N, s)
}

rBytes := sigDER.R.Bytes()
sBytes := sigS.Bytes()
sigBytes := make([]byte, 64)
// 0 pad the byte arrays from the left if they aren't big enough.
copy(sigBytes[32-len(rBytes):32], rBytes)
copy(sigBytes[64-len(sBytes):64], sBytes)
copy(sigBytes[32-len(r.Bytes()):32], r.Bytes())
copy(sigBytes[64-len(s.Bytes()):64], s.Bytes())

return sigBytes, nil
}
Expand All @@ -198,7 +203,7 @@ func getDevice() (SECP256K1, error) {

device, err := discoverLedger()
if err != nil {
return nil, errors.Wrap(err, "ledger nano S")
return nil, fmt.Errorf("ledger nano S: %w", err)
}

return device, nil
Expand Down Expand Up @@ -252,7 +257,7 @@ func getPubKeyUnsafe(device SECP256K1, path hd.BIP44Params) (types.PubKey, error
}

// re-serialize in the 33-byte compressed format
cmp, err := btcec.ParsePubKey(publicKey, btcec.S256())
cmp, err := btcec.ParsePubKey(publicKey)
if err != nil {
return nil, fmt.Errorf("error parsing public key: %v", err)
}
Expand All @@ -276,7 +281,7 @@ func getPubKeyAddrSafe(device SECP256K1, path hd.BIP44Params, hrp string) (types
}

// re-serialize in the 33-byte compressed format
cmp, err := btcec.ParsePubKey(publicKey, btcec.S256())
cmp, err := btcec.ParsePubKey(publicKey)
if err != nil {
return nil, "", fmt.Errorf("error parsing public key: %v", err)
}
Expand Down
Loading

0 comments on commit 0b64514

Please sign in to comment.