Skip to content

Commit

Permalink
fix: Implement gogoproto customtype to secp256r1 keys (#20027)
Browse files Browse the repository at this point in the history
Co-authored-by: Marko <marko@baricevic.me>
  • Loading branch information
facundomedica and tac0turtle committed Apr 12, 2024
1 parent ce373b6 commit 037cf98
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ Every module contains its own CHANGELOG.md. Please refer to the module you are i
* [#19833](https://github.com/cosmos/cosmos-sdk/pull/19833) Fix some places in which we call Remove inside a Walk.
* [#19851](https://github.com/cosmos/cosmos-sdk/pull/19851) Fix some places in which we call Remove inside a Walk (x/staking and x/gov).
* (baseapp) [#19970](https://github.com/cosmos/cosmos-sdk/pull/19970) Fix default config values to use no-op mempool as default.
* (crypto) [#20027](https://github.com/cosmos/cosmos-sdk/pull/20027) secp256r1 keys now implement gogoproto's customtype interface.
* (x/bank) [#20028](https://github.com/cosmos/cosmos-sdk/pull/20028) Align query with multi denoms for send-enabled.

### API Breaking Changes
Expand Down
25 changes: 25 additions & 0 deletions crypto/keys/secp256r1/privkey.go
Original file line number Diff line number Diff line change
@@ -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)
Expand Down Expand Up @@ -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 {
Expand Down
11 changes: 11 additions & 0 deletions crypto/keys/secp256r1/privkey_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
37 changes: 37 additions & 0 deletions crypto/keys/secp256r1/pubkey.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,29 @@
package secp256r1

import (
"encoding/base64"

cmtcrypto "github.com/cometbft/cometbft/crypto"
"github.com/cosmos/gogoproto/proto"

ecdsa "github.com/cosmos/cosmos-sdk/crypto/keys/internal/ecdsa"
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)
Expand Down Expand Up @@ -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 {
Expand Down
11 changes: 11 additions & 0 deletions crypto/keys/secp256r1/pubkey_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}

0 comments on commit 037cf98

Please sign in to comment.