From dc17934855242d4210ed2f7035e4b1fc3131808d Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Sun, 14 Apr 2024 08:59:30 +0200 Subject: [PATCH 1/3] fix: Implement gogoproto customtype to secp256r1 keys (backport #20027) (#20032) Co-authored-by: Facundo Medica <14063057+facundomedica@users.noreply.github.com> Co-authored-by: marbar3778 Co-authored-by: Marko --- CHANGELOG.md | 2 +- crypto/keys/secp256r1/privkey.go | 25 +++++++++++++ .../keys/secp256r1/privkey_internal_test.go | 11 ++++++ crypto/keys/secp256r1/pubkey.go | 37 +++++++++++++++++++ crypto/keys/secp256r1/pubkey_internal_test.go | 11 ++++++ 5 files changed, 85 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 569fa477947f..20b95e3131b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -511,4 +511,4 @@ extension interfaces. `module.Manager.Modules` is now of type `map[string]interf ## Previous Versions -[CHANGELOG of previous versions](https://github.com/cosmos/cosmos-sdk/blob/main/CHANGELOG.md#v0460---2022-07-26). +[CHANGELOG of previous versions](https://github.com/cosmos/cosmos-sdk/blob/main/CHANGELOG.md#v0460---2022-07-26). \ No newline at end of file diff --git a/crypto/keys/secp256r1/privkey.go b/crypto/keys/secp256r1/privkey.go index c6702111c738..a0ae1b069bc0 100644 --- a/crypto/keys/secp256r1/privkey.go +++ b/crypto/keys/secp256r1/privkey.go @@ -1,10 +1,14 @@ package secp256r1 import ( + "encoding/base64" + "github.com/cosmos/cosmos-sdk/crypto/keys/internal/ecdsa" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" ) +var _ customProtobufType = (*ecdsaSK)(nil) + // GenPrivKey generates a new secp256r1 private key. It uses operating system randomness. func GenPrivKey() (*PrivKey, error) { key, err := ecdsa.GenPrivKey(secp256r1) @@ -52,6 +56,27 @@ type ecdsaSK struct { ecdsa.PrivKey } +// Marshal implements customProtobufType. +func (sk ecdsaSK) Marshal() ([]byte, error) { + return sk.PrivKey.Bytes(), nil +} + +// MarshalJSON implements customProtobufType. +func (sk ecdsaSK) MarshalJSON() ([]byte, error) { + b64 := base64.StdEncoding.EncodeToString(sk.PrivKey.Bytes()) + return []byte(b64), nil +} + +// UnmarshalJSON implements customProtobufType. +func (sk *ecdsaSK) UnmarshalJSON(data []byte) error { + bz, err := base64.StdEncoding.DecodeString(string(data)) + if err != nil { + return err + } + + return sk.PrivKey.Unmarshal(bz, secp256r1, fieldSize) +} + // Size implements proto.Marshaler interface func (sk *ecdsaSK) Size() int { if sk == nil { diff --git a/crypto/keys/secp256r1/privkey_internal_test.go b/crypto/keys/secp256r1/privkey_internal_test.go index 771582d6a413..11b234191fc4 100644 --- a/crypto/keys/secp256r1/privkey_internal_test.go +++ b/crypto/keys/secp256r1/privkey_internal_test.go @@ -113,3 +113,14 @@ func (suite *SKSuite) TestSize() { var nilPk *ecdsaSK require.Equal(0, nilPk.Size(), "nil value must have zero size") } + +func (suite *SKSuite) TestJson() { + require := suite.Require() + asd := suite.sk.(*PrivKey) + bz, err := asd.Secret.MarshalJSON() + require.NoError(err) + + sk := &ecdsaSK{} + require.NoError(sk.UnmarshalJSON(bz)) + require.Equal(suite.sk.(*PrivKey).Secret, sk) +} diff --git a/crypto/keys/secp256r1/pubkey.go b/crypto/keys/secp256r1/pubkey.go index bf79c33cb9c1..9574994bac8c 100644 --- a/crypto/keys/secp256r1/pubkey.go +++ b/crypto/keys/secp256r1/pubkey.go @@ -1,6 +1,8 @@ package secp256r1 import ( + "encoding/base64" + tmcrypto "github.com/cometbft/cometbft/crypto" "github.com/cosmos/gogoproto/proto" @@ -8,6 +10,20 @@ import ( cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" ) +// customProtobufType is here to make sure that ecdsaPK and ecdsaSK implement the +// gogoproto customtype interface. +type customProtobufType interface { + Marshal() ([]byte, error) + MarshalTo(data []byte) (n int, err error) + Unmarshal(data []byte) error + Size() int + + MarshalJSON() ([]byte, error) + UnmarshalJSON(data []byte) error +} + +var _ customProtobufType = (*ecdsaPK)(nil) + // String implements proto.Message interface. func (m *PubKey) String() string { return m.Key.String(name) @@ -49,6 +65,27 @@ type ecdsaPK struct { ecdsa.PubKey } +// Marshal implements customProtobufType. +func (pk ecdsaPK) Marshal() ([]byte, error) { + return pk.PubKey.Bytes(), nil +} + +// MarshalJSON implements customProtobufType. +func (pk ecdsaPK) MarshalJSON() ([]byte, error) { + b64 := base64.StdEncoding.EncodeToString(pk.PubKey.Bytes()) + return []byte(b64), nil +} + +// UnmarshalJSON implements customProtobufType. +func (pk *ecdsaPK) UnmarshalJSON(data []byte) error { + bz, err := base64.StdEncoding.DecodeString(string(data)) + if err != nil { + return err + } + + return pk.PubKey.Unmarshal(bz, secp256r1, pubKeySize) +} + // Size implements proto.Marshaler interface func (pk *ecdsaPK) Size() int { if pk == nil { diff --git a/crypto/keys/secp256r1/pubkey_internal_test.go b/crypto/keys/secp256r1/pubkey_internal_test.go index eecbbb24d7da..f29eb15853d5 100644 --- a/crypto/keys/secp256r1/pubkey_internal_test.go +++ b/crypto/keys/secp256r1/pubkey_internal_test.go @@ -126,3 +126,14 @@ func (suite *PKSuite) TestSize() { var nilPk *ecdsaPK require.Equal(0, nilPk.Size(), "nil value must have zero size") } + +func (suite *PKSuite) TestJson() { + require := suite.Require() + + bz, err := suite.pk.Key.MarshalJSON() + require.NoError(err) + + pk := &ecdsaPK{} + require.NoError(pk.UnmarshalJSON(bz)) + require.Equal(suite.pk.Key, pk) +} From fbeaf8f1bd0f4ca77709df5732a931038361d496 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Wed, 17 Apr 2024 09:48:12 +0000 Subject: [PATCH 2/3] fix: secp256r1 json missing quotes (backport #20060) (#20070) Co-authored-by: Facundo Medica <14063057+facundomedica@users.noreply.github.com> --- crypto/keys/secp256r1/privkey.go | 4 ++-- crypto/keys/secp256r1/pubkey.go | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/crypto/keys/secp256r1/privkey.go b/crypto/keys/secp256r1/privkey.go index a0ae1b069bc0..3080dec21785 100644 --- a/crypto/keys/secp256r1/privkey.go +++ b/crypto/keys/secp256r1/privkey.go @@ -64,12 +64,12 @@ func (sk ecdsaSK) Marshal() ([]byte, error) { // MarshalJSON implements customProtobufType. func (sk ecdsaSK) MarshalJSON() ([]byte, error) { b64 := base64.StdEncoding.EncodeToString(sk.PrivKey.Bytes()) - return []byte(b64), nil + return []byte("\"" + b64 + "\""), nil } // UnmarshalJSON implements customProtobufType. func (sk *ecdsaSK) UnmarshalJSON(data []byte) error { - bz, err := base64.StdEncoding.DecodeString(string(data)) + bz, err := base64.StdEncoding.DecodeString(string(data[1 : len(data)-1])) if err != nil { return err } diff --git a/crypto/keys/secp256r1/pubkey.go b/crypto/keys/secp256r1/pubkey.go index 9574994bac8c..999b3ddc343d 100644 --- a/crypto/keys/secp256r1/pubkey.go +++ b/crypto/keys/secp256r1/pubkey.go @@ -73,12 +73,13 @@ func (pk ecdsaPK) Marshal() ([]byte, error) { // MarshalJSON implements customProtobufType. func (pk ecdsaPK) MarshalJSON() ([]byte, error) { b64 := base64.StdEncoding.EncodeToString(pk.PubKey.Bytes()) - return []byte(b64), nil + return []byte("\"" + b64 + "\""), nil } // UnmarshalJSON implements customProtobufType. func (pk *ecdsaPK) UnmarshalJSON(data []byte) error { - bz, err := base64.StdEncoding.DecodeString(string(data)) + // the string is quoted so we need to remove them + bz, err := base64.StdEncoding.DecodeString(string(data[1 : len(data)-1])) if err != nil { return err } From efb042d71da07416d4c17d85e97aae5625cdc815 Mon Sep 17 00:00:00 2001 From: MSalopek Date: Wed, 17 Apr 2024 13:01:21 +0200 Subject: [PATCH 3/3] add changelogs --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 20b95e3131b9..e8c5894176b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,15 @@ Ref: https://keepachangelog.com/en/1.0.0/ # Changelog +## v0.47.12-ics-lsm + +This is a special cosmos-sdk release with support for both ICS and LSM. + +### Bugfixes + +* (crypto) [#20073](https://github.com/cosmos/cosmos-sdk/pull/20073) Add secp256r1 parsing support (backport from main) + + ## v0.47.11-ics-lsm This is a special cosmos-sdk release with support for both ICS and LSM.