crypto: add secp256r1 (#8559)
* Optimize secp256k1 hashing * Add ADR-028 related functions * Update ed25519 * fix errors/handle * fix build * fix build * Add tests and update function names * wip * Use LengthPrefix for composed addresses * add tests for NewComposed * add module hash function * fix append * rollback ed25519 ADR-28 update * rollback ed25519 ADR-28 test * Adding Module tests and convert tests to test suite * convert store_key_test.go to test suite * rollback test check comment * any.pb.go update * generated proto files * wip * renames * wip2 * add String method to PBBytes * wip3 * add pubkey tests * adding cryptotypes.PrivKey methods * re-enable test * fix equals test * fix ecdsa object receiver * add ProtoMarshaler implementation and tests * move code to init and add interface registry * add bytes tests * merge Unmarshal with UnmarshalAmino * implement ProtoMarshaler to ecdsaSK * remove bytes.go * add private key marshaling tests * break tests into 2 suites * add signature tests * remove TODO * remove bytes.proto * adding changelog * Update CHANGELOG.md * Update crypto/keys/ecdsa/ecdsa_privkey.go * Update crypto/keys/ecdsa/ecdsa_pubkey.go * comments: add dot (.) at the end * update comments * update commented code * rename files * remove Amino methods * use 2 spaces in protocgen.sh * rollback changes in protocgen.sh * add MessageName * rework ecdsa proto structure * move ecdsa to internal package * add secp256r1 proto * refactore proto definition for secp256r1 * fix err check * update comments * create const for fieldSize+1 * simplify the PubKey.String test * Apply suggestions from code review Co-authored-by: Jonathan Gimeno <jgimeno@gmail.com> * Update doc comments: SDK Interface -> sdk.Interface * rename init.go to doc.go * Add PubKey.Type() test * Revert "Update doc comments: SDK Interface -> sdk.Interface" This reverts commit 01f2b4f5efcd79a452483bcda152db54a8fbfee2. * Use cryptotypes.Address instead of tmcrypto * Revert "Use cryptotypes.Address instead of tmcrypto" This reverts commit 15b866ae67bdb7ca4872f4089fcab19f9e2e3608. This issue will be solved in https://github.com/cosmos/cosmos-sdk/issues/8775 * add link to ANSI X9.62 * move init.go -> doc.go * use proto.MessageName() Co-authored-by: Alessio Treglia <alessio@tendermint.com> Co-authored-by: Jonathan Gimeno <jgimeno@gmail.com>
This commit is contained in:
parent
eef8d4dc5d
commit
c66f1f7efe
@ -36,6 +36,10 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## Features
|
||||
|
||||
* [\#8559](https://github.com/cosmos/cosmos-sdk/pull/8559) Adding Protobuf compatible secp256r1 ECDSA signatures.
|
||||
|
||||
### Client Breaking Changes
|
||||
|
||||
* [\#8363](https://github.com/cosmos/cosmos-sdk/pull/8363) Addresses no longer have a fixed 20-byte length. From the SDK modules' point of view, any 1-255 bytes-long byte array is a valid address.
|
||||
@ -137,7 +141,7 @@ he Cosmos Hub) should not use this release or any release in the v0.41.x series.
|
||||
### State Machine Breaking
|
||||
|
||||
* (x/ibc) [\#8266](https://github.com/cosmos/cosmos-sdk/issues/8266) Add amino JSON support for IBC MsgTransfer in order to support Ledger text signing transfer transactions.
|
||||
* (x/ibc) [\#8404](https://github.com/cosmos/cosmos-sdk/pull/8404) Reorder IBC `ChanOpenAck` and `ChanOpenConfirm` handler execution to perform core handler first, followed by application callbacks.
|
||||
* (x/ibc) [\#8404](https://github.com/cosmos/cosmos-sdk/pull/8404) Reorder IBC `ChanOpenAck` and `ChanOpenConfirm` handler execution to perform core handler first, followed by application callbacks.
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
|
||||
@ -476,10 +476,7 @@ func (m *Any) Unmarshal(dAtA []byte) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthAny
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthAny
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
|
||||
@ -5,13 +5,16 @@ import (
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys/multisig"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256r1"
|
||||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
)
|
||||
|
||||
// RegisterInterfaces registers the sdk.Tx interface.
|
||||
func RegisterInterfaces(registry codectypes.InterfaceRegistry) {
|
||||
registry.RegisterInterface("cosmos.crypto.PubKey", (*cryptotypes.PubKey)(nil))
|
||||
registry.RegisterImplementations((*cryptotypes.PubKey)(nil), &ed25519.PubKey{})
|
||||
registry.RegisterImplementations((*cryptotypes.PubKey)(nil), &secp256k1.PubKey{})
|
||||
registry.RegisterImplementations((*cryptotypes.PubKey)(nil), &multisig.LegacyAminoPubKey{})
|
||||
var pk *cryptotypes.PubKey
|
||||
registry.RegisterInterface("cosmos.crypto.PubKey", pk)
|
||||
registry.RegisterImplementations(pk, &ed25519.PubKey{})
|
||||
registry.RegisterImplementations(pk, &secp256k1.PubKey{})
|
||||
registry.RegisterImplementations(pk, &multisig.LegacyAminoPubKey{})
|
||||
secp256r1.RegisterInterfaces(registry)
|
||||
}
|
||||
|
||||
3
crypto/keys/internal/ecdsa/doc.go
Normal file
3
crypto/keys/internal/ecdsa/doc.go
Normal file
@ -0,0 +1,3 @@
|
||||
// Package ECDSA implements Cosmos-SDK compatible ECDSA public and private key. The keys
|
||||
// can be serialized.
|
||||
package ecdsa
|
||||
69
crypto/keys/internal/ecdsa/privkey.go
Normal file
69
crypto/keys/internal/ecdsa/privkey.go
Normal file
@ -0,0 +1,69 @@
|
||||
package ecdsa
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
// GenPrivKey generates a new secp256r1 private key. It uses operating system randomness.
|
||||
func GenPrivKey(curve elliptic.Curve) (PrivKey, error) {
|
||||
key, err := ecdsa.GenerateKey(curve, rand.Reader)
|
||||
if err != nil {
|
||||
return PrivKey{}, err
|
||||
}
|
||||
return PrivKey{*key}, nil
|
||||
}
|
||||
|
||||
type PrivKey struct {
|
||||
ecdsa.PrivateKey
|
||||
}
|
||||
|
||||
// PubKey returns ECDSA public key associated with this private key.
|
||||
func (sk *PrivKey) PubKey() PubKey {
|
||||
return PubKey{sk.PublicKey, nil}
|
||||
}
|
||||
|
||||
// Bytes serialize the private key using big-endian.
|
||||
func (sk *PrivKey) Bytes() []byte {
|
||||
if sk == nil {
|
||||
return nil
|
||||
}
|
||||
fieldSize := (sk.Curve.Params().BitSize + 7) / 8
|
||||
bz := make([]byte, fieldSize)
|
||||
sk.D.FillBytes(bz)
|
||||
return bz
|
||||
}
|
||||
|
||||
// Sign hashes and signs the message usign ECDSA. Implements SDK PrivKey interface.
|
||||
func (sk *PrivKey) Sign(msg []byte) ([]byte, error) {
|
||||
digest := sha256.Sum256(msg)
|
||||
return sk.PrivateKey.Sign(rand.Reader, digest[:], nil)
|
||||
}
|
||||
|
||||
// String returns a string representation of the public key based on the curveName.
|
||||
func (sk *PrivKey) String(name string) string {
|
||||
return name + "{-}"
|
||||
}
|
||||
|
||||
// MarshalTo implements proto.Marshaler interface.
|
||||
func (sk *PrivKey) MarshalTo(dAtA []byte) (int, error) {
|
||||
bz := sk.Bytes()
|
||||
copy(dAtA, bz)
|
||||
return len(bz), nil
|
||||
}
|
||||
|
||||
// Unmarshal implements proto.Marshaler interface.
|
||||
func (sk *PrivKey) Unmarshal(bz []byte, curve elliptic.Curve, expectedSize int) error {
|
||||
if len(bz) != expectedSize {
|
||||
return fmt.Errorf("wrong ECDSA SK bytes, expecting %d bytes", expectedSize)
|
||||
}
|
||||
|
||||
sk.Curve = curve
|
||||
sk.D = new(big.Int).SetBytes(bz)
|
||||
sk.X, sk.Y = curve.ScalarBaseMult(bz)
|
||||
return nil
|
||||
}
|
||||
66
crypto/keys/internal/ecdsa/privkey_internal_test.go
Normal file
66
crypto/keys/internal/ecdsa/privkey_internal_test.go
Normal file
@ -0,0 +1,66 @@
|
||||
package ecdsa
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/tendermint/tendermint/crypto"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
func TestSKSuite(t *testing.T) {
|
||||
suite.Run(t, new(SKSuite))
|
||||
}
|
||||
|
||||
type SKSuite struct{ CommonSuite }
|
||||
|
||||
func (suite *SKSuite) TestString() {
|
||||
const prefix = "abc"
|
||||
suite.Require().Equal(prefix+"{-}", suite.sk.String(prefix))
|
||||
}
|
||||
|
||||
func (suite *SKSuite) TestPubKey() {
|
||||
pk := suite.sk.PubKey()
|
||||
suite.True(suite.sk.PublicKey.Equal(&pk.PublicKey))
|
||||
}
|
||||
|
||||
func (suite *SKSuite) Bytes() {
|
||||
bz := suite.sk.Bytes()
|
||||
suite.Len(bz, 32)
|
||||
var sk *PrivKey
|
||||
suite.Nil(sk.Bytes())
|
||||
}
|
||||
|
||||
func (suite *SKSuite) TestMarshal() {
|
||||
require := suite.Require()
|
||||
const size = 32
|
||||
|
||||
var buffer = make([]byte, size)
|
||||
suite.sk.MarshalTo(buffer)
|
||||
|
||||
var sk = new(PrivKey)
|
||||
err := sk.Unmarshal(buffer, secp256r1, size)
|
||||
require.NoError(err)
|
||||
require.True(sk.Equal(&suite.sk.PrivateKey))
|
||||
}
|
||||
|
||||
func (suite *SKSuite) TestSign() {
|
||||
require := suite.Require()
|
||||
|
||||
msg := crypto.CRandBytes(1000)
|
||||
sig, err := suite.sk.Sign(msg)
|
||||
require.NoError(err)
|
||||
sigCpy := make([]byte, len(sig))
|
||||
copy(sigCpy, sig)
|
||||
require.True(suite.pk.VerifySignature(msg, sigCpy))
|
||||
|
||||
// Mutate the signature
|
||||
for i := range sig {
|
||||
sigCpy[i] ^= byte(i + 1)
|
||||
require.False(suite.pk.VerifySignature(msg, sigCpy))
|
||||
}
|
||||
|
||||
// Mutate the message
|
||||
msg[1] ^= byte(2)
|
||||
require.False(suite.pk.VerifySignature(msg, sig))
|
||||
}
|
||||
83
crypto/keys/internal/ecdsa/pubkey.go
Normal file
83
crypto/keys/internal/ecdsa/pubkey.go
Normal file
@ -0,0 +1,83 @@
|
||||
package ecdsa
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/sha256"
|
||||
"encoding/asn1"
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
tmcrypto "github.com/tendermint/tendermint/crypto"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/types/address"
|
||||
"github.com/cosmos/cosmos-sdk/types/errors"
|
||||
)
|
||||
|
||||
// signature holds the r and s values of an ECDSA signature.
|
||||
type signature struct {
|
||||
R, S *big.Int
|
||||
}
|
||||
|
||||
type PubKey struct {
|
||||
ecdsa.PublicKey
|
||||
|
||||
// cache
|
||||
address tmcrypto.Address
|
||||
}
|
||||
|
||||
// Address creates an ADR-28 address for ECDSA keys. protoName is a concrete proto structure id.
|
||||
func (pk *PubKey) Address(protoName string) tmcrypto.Address {
|
||||
if pk.address == nil {
|
||||
pk.address = address.Hash(protoName, pk.Bytes())
|
||||
}
|
||||
return pk.address
|
||||
}
|
||||
|
||||
// Bytes returns the byte representation of the public key using a compressed form
|
||||
// specified in section 4.3.6 of ANSI X9.62 with first byte being the curve type.
|
||||
func (pk *PubKey) Bytes() []byte {
|
||||
if pk == nil {
|
||||
return nil
|
||||
}
|
||||
return elliptic.MarshalCompressed(pk.Curve, pk.X, pk.Y)
|
||||
}
|
||||
|
||||
// VerifySignature checks if sig is a valid ECDSA signature for msg.
|
||||
func (pk *PubKey) VerifySignature(msg []byte, sig []byte) bool {
|
||||
s := new(signature)
|
||||
if _, err := asn1.Unmarshal(sig, s); err != nil || s == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
h := sha256.Sum256(msg)
|
||||
return ecdsa.Verify(&pk.PublicKey, h[:], s.R, s.S)
|
||||
}
|
||||
|
||||
// String returns a string representation of the public key based on the curveName.
|
||||
func (pk *PubKey) String(curveName string) string {
|
||||
return fmt.Sprintf("%s{%X}", curveName, pk.Bytes())
|
||||
}
|
||||
|
||||
// **** Proto Marshaler ****
|
||||
|
||||
// MarshalTo implements proto.Marshaler interface.
|
||||
func (pk *PubKey) MarshalTo(dAtA []byte) (int, error) {
|
||||
bz := pk.Bytes()
|
||||
copy(dAtA, bz)
|
||||
return len(bz), nil
|
||||
}
|
||||
|
||||
// Unmarshal implements proto.Marshaler interface.
|
||||
func (pk *PubKey) Unmarshal(bz []byte, curve elliptic.Curve, expectedSize int) error {
|
||||
if len(bz) != expectedSize {
|
||||
return errors.Wrapf(errors.ErrInvalidPubKey, "wrong ECDSA PK bytes, expecting %d bytes, got %d", expectedSize, len(bz))
|
||||
}
|
||||
cpk := ecdsa.PublicKey{Curve: curve}
|
||||
cpk.X, cpk.Y = elliptic.UnmarshalCompressed(curve, bz)
|
||||
if cpk.X == nil || cpk.Y == nil {
|
||||
return errors.Wrapf(errors.ErrInvalidPubKey, "wrong ECDSA PK bytes, unknown curve type: %d", bz[0])
|
||||
}
|
||||
pk.PublicKey = cpk
|
||||
return nil
|
||||
}
|
||||
69
crypto/keys/internal/ecdsa/pubkey_internal_test.go
Normal file
69
crypto/keys/internal/ecdsa/pubkey_internal_test.go
Normal file
@ -0,0 +1,69 @@
|
||||
package ecdsa
|
||||
|
||||
import (
|
||||
"crypto/elliptic"
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
var secp256r1 = elliptic.P256()
|
||||
|
||||
func GenSecp256r1() (PrivKey, error) {
|
||||
return GenPrivKey(secp256r1)
|
||||
}
|
||||
|
||||
func TestPKSuite(t *testing.T) {
|
||||
suite.Run(t, new(PKSuite))
|
||||
}
|
||||
|
||||
type CommonSuite struct {
|
||||
suite.Suite
|
||||
pk PubKey
|
||||
sk PrivKey
|
||||
}
|
||||
|
||||
func (suite *CommonSuite) SetupSuite() {
|
||||
sk, err := GenSecp256r1()
|
||||
suite.Require().NoError(err)
|
||||
suite.sk = sk
|
||||
suite.pk = sk.PubKey()
|
||||
}
|
||||
|
||||
type PKSuite struct{ CommonSuite }
|
||||
|
||||
func (suite *PKSuite) TestString() {
|
||||
assert := suite.Assert()
|
||||
require := suite.Require()
|
||||
|
||||
prefix := "abc"
|
||||
pkStr := suite.pk.String(prefix)
|
||||
assert.Equal(prefix+"{", pkStr[:len(prefix)+1])
|
||||
assert.EqualValues('}', pkStr[len(pkStr)-1])
|
||||
|
||||
bz, err := hex.DecodeString(pkStr[len(prefix)+1 : len(pkStr)-1])
|
||||
require.NoError(err)
|
||||
assert.EqualValues(suite.pk.Bytes(), bz)
|
||||
}
|
||||
|
||||
func (suite *PKSuite) TestBytes() {
|
||||
require := suite.Require()
|
||||
var pk *PubKey
|
||||
require.Nil(pk.Bytes())
|
||||
}
|
||||
|
||||
func (suite *PKSuite) TestMarshal() {
|
||||
require := suite.Require()
|
||||
const size = 33 // secp256r1 size
|
||||
|
||||
var buffer = make([]byte, size)
|
||||
n, err := suite.pk.MarshalTo(buffer)
|
||||
require.NoError(err)
|
||||
require.Equal(size, n)
|
||||
|
||||
var pk = new(PubKey)
|
||||
err = pk.Unmarshal(buffer, secp256r1, size)
|
||||
require.NoError(err)
|
||||
require.True(pk.PublicKey.Equal(&suite.pk.PublicKey))
|
||||
}
|
||||
35
crypto/keys/secp256r1/doc.go
Normal file
35
crypto/keys/secp256r1/doc.go
Normal file
@ -0,0 +1,35 @@
|
||||
// Package secp256r1 implements Cosmos-SDK compatible ECDSA public and private key. The keys
|
||||
// can be protobuf serialized and packed in Any.
|
||||
package secp256r1
|
||||
|
||||
import (
|
||||
"crypto/elliptic"
|
||||
"fmt"
|
||||
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
)
|
||||
|
||||
const (
|
||||
// fieldSize is the curve domain size.
|
||||
fieldSize = 32
|
||||
pubKeySize = fieldSize + 1
|
||||
|
||||
name = "secp256r1"
|
||||
)
|
||||
|
||||
var secp256r1 elliptic.Curve
|
||||
|
||||
func init() {
|
||||
secp256r1 = elliptic.P256()
|
||||
// pubKeySize is ceil of field bit size + 1 for the sign
|
||||
expected := (secp256r1.Params().BitSize + 7) / 8
|
||||
if expected != fieldSize {
|
||||
panic(fmt.Sprintf("Wrong secp256r1 curve fieldSize=%d, expecting=%d", fieldSize, expected))
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterInterfaces adds secp256r1 PubKey to pubkey registry
|
||||
func RegisterInterfaces(registry codectypes.InterfaceRegistry) {
|
||||
registry.RegisterImplementations((*cryptotypes.PubKey)(nil), &PubKey{})
|
||||
}
|
||||
503
crypto/keys/secp256r1/keys.pb.go
Normal file
503
crypto/keys/secp256r1/keys.pb.go
Normal file
@ -0,0 +1,503 @@
|
||||
// Code generated by protoc-gen-gogo. DO NOT EDIT.
|
||||
// source: cosmos/crypto/secp256r1/keys.proto
|
||||
|
||||
package secp256r1
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
_ "github.com/gogo/protobuf/gogoproto"
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
io "io"
|
||||
math "math"
|
||||
math_bits "math/bits"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
// PubKey defines a secp256r1 ECDSA public key.
|
||||
type PubKey struct {
|
||||
// Point on secp256r1 curve in a compressed representation as specified in section
|
||||
// 4.3.6 of ANSI X9.62.
|
||||
Key *ecdsaPK `protobuf:"bytes,1,opt,name=key,proto3,customtype=ecdsaPK" json:"key,omitempty"`
|
||||
}
|
||||
|
||||
func (m *PubKey) Reset() { *m = PubKey{} }
|
||||
func (*PubKey) ProtoMessage() {}
|
||||
func (*PubKey) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_b90c18415095c0c3, []int{0}
|
||||
}
|
||||
func (m *PubKey) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *PubKey) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
if deterministic {
|
||||
return xxx_messageInfo_PubKey.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalToSizedBuffer(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (m *PubKey) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_PubKey.Merge(m, src)
|
||||
}
|
||||
func (m *PubKey) XXX_Size() int {
|
||||
return m.Size()
|
||||
}
|
||||
func (m *PubKey) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_PubKey.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_PubKey proto.InternalMessageInfo
|
||||
|
||||
func (*PubKey) XXX_MessageName() string {
|
||||
return "cosmos.crypto.secp256r1.PubKey"
|
||||
}
|
||||
|
||||
// PrivKey defines a secp256r1 ECDSA private key.
|
||||
type PrivKey struct {
|
||||
// secret number serialized using big-endian encoding
|
||||
Secret *ecdsaSK `protobuf:"bytes,1,opt,name=secret,proto3,customtype=ecdsaSK" json:"secret,omitempty"`
|
||||
}
|
||||
|
||||
func (m *PrivKey) Reset() { *m = PrivKey{} }
|
||||
func (*PrivKey) ProtoMessage() {}
|
||||
func (*PrivKey) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_b90c18415095c0c3, []int{1}
|
||||
}
|
||||
func (m *PrivKey) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *PrivKey) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
if deterministic {
|
||||
return xxx_messageInfo_PrivKey.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalToSizedBuffer(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (m *PrivKey) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_PrivKey.Merge(m, src)
|
||||
}
|
||||
func (m *PrivKey) XXX_Size() int {
|
||||
return m.Size()
|
||||
}
|
||||
func (m *PrivKey) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_PrivKey.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_PrivKey proto.InternalMessageInfo
|
||||
|
||||
func (*PrivKey) XXX_MessageName() string {
|
||||
return "cosmos.crypto.secp256r1.PrivKey"
|
||||
}
|
||||
func init() {
|
||||
proto.RegisterType((*PubKey)(nil), "cosmos.crypto.secp256r1.PubKey")
|
||||
proto.RegisterType((*PrivKey)(nil), "cosmos.crypto.secp256r1.PrivKey")
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterFile("cosmos/crypto/secp256r1/keys.proto", fileDescriptor_b90c18415095c0c3)
|
||||
}
|
||||
|
||||
var fileDescriptor_b90c18415095c0c3 = []byte{
|
||||
// 221 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x4a, 0xce, 0x2f, 0xce,
|
||||
0xcd, 0x2f, 0xd6, 0x4f, 0x2e, 0xaa, 0x2c, 0x28, 0xc9, 0xd7, 0x2f, 0x4e, 0x4d, 0x2e, 0x30, 0x32,
|
||||
0x35, 0x2b, 0x32, 0xd4, 0xcf, 0x4e, 0xad, 0x2c, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12,
|
||||
0x87, 0xa8, 0xd1, 0x83, 0xa8, 0xd1, 0x83, 0xab, 0x91, 0x12, 0x49, 0xcf, 0x4f, 0xcf, 0x07, 0xab,
|
||||
0xd1, 0x07, 0xb1, 0x20, 0xca, 0x95, 0xd4, 0xb9, 0xd8, 0x02, 0x4a, 0x93, 0xbc, 0x53, 0x2b, 0x85,
|
||||
0x64, 0xb9, 0x98, 0xb3, 0x53, 0x2b, 0x25, 0x18, 0x15, 0x18, 0x35, 0x78, 0x9c, 0xb8, 0x6f, 0xdd,
|
||||
0x93, 0x67, 0x4f, 0x4d, 0x4e, 0x29, 0x4e, 0x0c, 0xf0, 0x0e, 0x02, 0x89, 0x2b, 0xe9, 0x71, 0xb1,
|
||||
0x07, 0x14, 0x65, 0x96, 0x81, 0x54, 0x2a, 0x73, 0xb1, 0x15, 0xa7, 0x26, 0x17, 0xa5, 0x96, 0x60,
|
||||
0x28, 0x0e, 0xf6, 0x0e, 0x82, 0x4a, 0x39, 0x45, 0x9c, 0x78, 0x28, 0xc7, 0x70, 0xe3, 0xa1, 0x1c,
|
||||
0xc3, 0x89, 0x47, 0x72, 0x8c, 0x17, 0x1e, 0xc9, 0x31, 0x3e, 0x78, 0x24, 0xc7, 0x38, 0xe1, 0xb1,
|
||||
0x1c, 0xc3, 0x89, 0xc7, 0x72, 0x8c, 0x17, 0x1e, 0xcb, 0x31, 0xdc, 0x78, 0x2c, 0xc7, 0x10, 0x65,
|
||||
0x94, 0x9e, 0x59, 0x92, 0x51, 0x9a, 0xa4, 0x97, 0x9c, 0x9f, 0xab, 0x0f, 0xf3, 0x1c, 0x98, 0xd2,
|
||||
0x2d, 0x4e, 0xc9, 0x86, 0xf9, 0x13, 0xe4, 0x3b, 0x84, 0x67, 0x93, 0xd8, 0xc0, 0x2e, 0x37, 0x06,
|
||||
0x04, 0x00, 0x00, 0xff, 0xff, 0xe0, 0x65, 0x08, 0x5c, 0x0e, 0x01, 0x00, 0x00,
|
||||
}
|
||||
|
||||
func (m *PubKey) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *PubKey) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.Size()
|
||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *PubKey) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.Key != nil {
|
||||
{
|
||||
size := m.Key.Size()
|
||||
i -= size
|
||||
if _, err := m.Key.MarshalTo(dAtA[i:]); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i = encodeVarintKeys(dAtA, i, uint64(size))
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
}
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func (m *PrivKey) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *PrivKey) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.Size()
|
||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *PrivKey) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.Secret != nil {
|
||||
{
|
||||
size := m.Secret.Size()
|
||||
i -= size
|
||||
if _, err := m.Secret.MarshalTo(dAtA[i:]); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i = encodeVarintKeys(dAtA, i, uint64(size))
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
}
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func encodeVarintKeys(dAtA []byte, offset int, v uint64) int {
|
||||
offset -= sovKeys(v)
|
||||
base := offset
|
||||
for v >= 1<<7 {
|
||||
dAtA[offset] = uint8(v&0x7f | 0x80)
|
||||
v >>= 7
|
||||
offset++
|
||||
}
|
||||
dAtA[offset] = uint8(v)
|
||||
return base
|
||||
}
|
||||
func (m *PubKey) Size() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
if m.Key != nil {
|
||||
l = m.Key.Size()
|
||||
n += 1 + l + sovKeys(uint64(l))
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *PrivKey) Size() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
if m.Secret != nil {
|
||||
l = m.Secret.Size()
|
||||
n += 1 + l + sovKeys(uint64(l))
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func sovKeys(x uint64) (n int) {
|
||||
return (math_bits.Len64(x|1) + 6) / 7
|
||||
}
|
||||
func sozKeys(x uint64) (n int) {
|
||||
return sovKeys(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
||||
}
|
||||
func (m *PubKey) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowKeys
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: PubKey: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: PubKey: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType)
|
||||
}
|
||||
var byteLen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowKeys
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
byteLen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if byteLen < 0 {
|
||||
return ErrInvalidLengthKeys
|
||||
}
|
||||
postIndex := iNdEx + byteLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthKeys
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
var v ecdsaPK
|
||||
m.Key = &v
|
||||
if err := m.Key.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipKeys(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthKeys
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *PrivKey) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowKeys
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: PrivKey: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: PrivKey: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Secret", wireType)
|
||||
}
|
||||
var byteLen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowKeys
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
byteLen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if byteLen < 0 {
|
||||
return ErrInvalidLengthKeys
|
||||
}
|
||||
postIndex := iNdEx + byteLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthKeys
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
var v ecdsaSK
|
||||
m.Secret = &v
|
||||
if err := m.Secret.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipKeys(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthKeys
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func skipKeys(dAtA []byte) (n int, err error) {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
depth := 0
|
||||
for iNdEx < l {
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowKeys
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
wireType := int(wire & 0x7)
|
||||
switch wireType {
|
||||
case 0:
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowKeys
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx++
|
||||
if dAtA[iNdEx-1] < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 1:
|
||||
iNdEx += 8
|
||||
case 2:
|
||||
var length int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowKeys
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
length |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if length < 0 {
|
||||
return 0, ErrInvalidLengthKeys
|
||||
}
|
||||
iNdEx += length
|
||||
case 3:
|
||||
depth++
|
||||
case 4:
|
||||
if depth == 0 {
|
||||
return 0, ErrUnexpectedEndOfGroupKeys
|
||||
}
|
||||
depth--
|
||||
case 5:
|
||||
iNdEx += 4
|
||||
default:
|
||||
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
|
||||
}
|
||||
if iNdEx < 0 {
|
||||
return 0, ErrInvalidLengthKeys
|
||||
}
|
||||
if depth == 0 {
|
||||
return iNdEx, nil
|
||||
}
|
||||
}
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
|
||||
var (
|
||||
ErrInvalidLengthKeys = fmt.Errorf("proto: negative length found during unmarshaling")
|
||||
ErrIntOverflowKeys = fmt.Errorf("proto: integer overflow")
|
||||
ErrUnexpectedEndOfGroupKeys = fmt.Errorf("proto: unexpected end of group")
|
||||
)
|
||||
63
crypto/keys/secp256r1/privkey.go
Normal file
63
crypto/keys/secp256r1/privkey.go
Normal file
@ -0,0 +1,63 @@
|
||||
package secp256r1
|
||||
|
||||
import (
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys/internal/ecdsa"
|
||||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
)
|
||||
|
||||
// GenPrivKey generates a new secp256r1 private key. It uses operating system randomness.
|
||||
func GenPrivKey() (*PrivKey, error) {
|
||||
key, err := ecdsa.GenPrivKey(secp256r1)
|
||||
return &PrivKey{&ecdsaSK{key}}, err
|
||||
}
|
||||
|
||||
// PubKey implements SDK PrivKey interface.
|
||||
func (m *PrivKey) PubKey() cryptotypes.PubKey {
|
||||
return &PubKey{&ecdsaPK{m.Secret.PubKey()}}
|
||||
}
|
||||
|
||||
// String implements SDK proto.Message interface.
|
||||
func (m *PrivKey) String() string {
|
||||
return m.Secret.String(name)
|
||||
}
|
||||
|
||||
// Type returns key type name. Implements SDK PrivKey interface.
|
||||
func (m *PrivKey) Type() string {
|
||||
return name
|
||||
}
|
||||
|
||||
// Sign hashes and signs the message usign ECDSA. Implements sdk.PrivKey interface.
|
||||
func (m *PrivKey) Sign(msg []byte) ([]byte, error) {
|
||||
return m.Secret.Sign(msg)
|
||||
}
|
||||
|
||||
// Bytes serialize the private key.
|
||||
func (m *PrivKey) Bytes() []byte {
|
||||
return m.Secret.Bytes()
|
||||
}
|
||||
|
||||
// Equals implements SDK PrivKey interface.
|
||||
func (m *PrivKey) Equals(other cryptotypes.LedgerPrivKey) bool {
|
||||
sk2, ok := other.(*PrivKey)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return m.Secret.Equal(&sk2.Secret.PrivateKey)
|
||||
}
|
||||
|
||||
type ecdsaSK struct {
|
||||
ecdsa.PrivKey
|
||||
}
|
||||
|
||||
// Size implements proto.Marshaler interface
|
||||
func (sk *ecdsaSK) Size() int {
|
||||
if sk == nil {
|
||||
return 0
|
||||
}
|
||||
return fieldSize
|
||||
}
|
||||
|
||||
// Unmarshal implements proto.Marshaler interface
|
||||
func (sk *ecdsaSK) Unmarshal(bz []byte) error {
|
||||
return sk.PrivKey.Unmarshal(bz, secp256r1, fieldSize)
|
||||
}
|
||||
115
crypto/keys/secp256r1/privkey_internal_test.go
Normal file
115
crypto/keys/secp256r1/privkey_internal_test.go
Normal file
@ -0,0 +1,115 @@
|
||||
package secp256r1
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/tendermint/tendermint/crypto"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/codec/types"
|
||||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
var _ cryptotypes.PrivKey = &PrivKey{}
|
||||
|
||||
func TestSKSuite(t *testing.T) {
|
||||
suite.Run(t, new(SKSuite))
|
||||
}
|
||||
|
||||
type SKSuite struct{ CommonSuite }
|
||||
|
||||
func (suite *SKSuite) TestString() {
|
||||
suite.Require().Equal("secp256r1{-}", suite.sk.String())
|
||||
}
|
||||
|
||||
func (suite *SKSuite) TestEquals() {
|
||||
require := suite.Require()
|
||||
|
||||
skOther, err := GenPrivKey()
|
||||
require.NoError(err)
|
||||
require.False(suite.sk.Equals(skOther))
|
||||
|
||||
skOther2 := &PrivKey{skOther.Secret}
|
||||
require.True(skOther.Equals(skOther2))
|
||||
require.True(skOther2.Equals(skOther), "Equals must be reflexive")
|
||||
}
|
||||
|
||||
func (suite *SKSuite) TestPubKey() {
|
||||
pk := suite.sk.PubKey()
|
||||
suite.True(suite.sk.(*PrivKey).Secret.PublicKey.Equal(&pk.(*PubKey).Key.PublicKey))
|
||||
}
|
||||
|
||||
func (suite *SKSuite) Bytes() {
|
||||
bz := suite.sk.Bytes()
|
||||
suite.Len(bz, fieldSize)
|
||||
var sk *PrivKey
|
||||
suite.Nil(sk.Bytes())
|
||||
}
|
||||
|
||||
func (suite *SKSuite) TestMarshalProto() {
|
||||
require := suite.Require()
|
||||
|
||||
/**** test structure marshalling ****/
|
||||
|
||||
var sk PrivKey
|
||||
bz, err := proto.Marshal(suite.sk)
|
||||
require.NoError(err)
|
||||
require.NoError(proto.Unmarshal(bz, &sk))
|
||||
require.True(sk.Equals(suite.sk))
|
||||
|
||||
/**** test structure marshalling with codec ****/
|
||||
|
||||
sk = PrivKey{}
|
||||
registry := types.NewInterfaceRegistry()
|
||||
cdc := codec.NewProtoCodec(registry)
|
||||
bz, err = cdc.MarshalBinaryBare(suite.sk.(*PrivKey))
|
||||
require.NoError(err)
|
||||
require.NoError(cdc.UnmarshalBinaryBare(bz, &sk))
|
||||
require.True(sk.Equals(suite.sk))
|
||||
|
||||
const bufSize = 100
|
||||
bz2 := make([]byte, bufSize)
|
||||
skCpy := suite.sk.(*PrivKey)
|
||||
_, err = skCpy.MarshalTo(bz2)
|
||||
require.NoError(err)
|
||||
require.Len(bz2, bufSize)
|
||||
require.Equal(bz, bz2[:sk.Size()])
|
||||
|
||||
bz2 = make([]byte, bufSize)
|
||||
_, err = skCpy.MarshalToSizedBuffer(bz2)
|
||||
require.NoError(err)
|
||||
require.Len(bz2, bufSize)
|
||||
require.Equal(bz, bz2[(bufSize-sk.Size()):])
|
||||
}
|
||||
|
||||
func (suite *SKSuite) TestSign() {
|
||||
require := suite.Require()
|
||||
|
||||
msg := crypto.CRandBytes(1000)
|
||||
sig, err := suite.sk.Sign(msg)
|
||||
require.NoError(err)
|
||||
sigCpy := make([]byte, len(sig))
|
||||
copy(sigCpy, sig)
|
||||
require.True(suite.pk.VerifySignature(msg, sigCpy))
|
||||
|
||||
// Mutate the signature
|
||||
for i := range sig {
|
||||
sigCpy[i] ^= byte(i + 1)
|
||||
require.False(suite.pk.VerifySignature(msg, sigCpy))
|
||||
}
|
||||
|
||||
// Mutate the message
|
||||
msg[1] ^= byte(2)
|
||||
require.False(suite.pk.VerifySignature(msg, sig))
|
||||
}
|
||||
|
||||
func (suite *SKSuite) TestSize() {
|
||||
require := suite.Require()
|
||||
var pk ecdsaSK
|
||||
require.Equal(pk.Size(), len(suite.sk.Bytes()))
|
||||
|
||||
var nilPk *ecdsaSK
|
||||
require.Equal(0, nilPk.Size(), "nil value must have zero size")
|
||||
}
|
||||
60
crypto/keys/secp256r1/pubkey.go
Normal file
60
crypto/keys/secp256r1/pubkey.go
Normal file
@ -0,0 +1,60 @@
|
||||
package secp256r1
|
||||
|
||||
import (
|
||||
"github.com/gogo/protobuf/proto"
|
||||
tmcrypto "github.com/tendermint/tendermint/crypto"
|
||||
|
||||
ecdsa "github.com/cosmos/cosmos-sdk/crypto/keys/internal/ecdsa"
|
||||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
)
|
||||
|
||||
// String implements proto.Message interface.
|
||||
func (m *PubKey) String() string {
|
||||
return m.Key.String(name)
|
||||
}
|
||||
|
||||
// Bytes implements SDK PubKey interface.
|
||||
func (m *PubKey) Bytes() []byte {
|
||||
return m.Key.Bytes()
|
||||
}
|
||||
|
||||
// Equals implements SDK PubKey interface.
|
||||
func (m *PubKey) Equals(other cryptotypes.PubKey) bool {
|
||||
pk2, ok := other.(*PubKey)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return m.Key.Equal(&pk2.Key.PublicKey)
|
||||
}
|
||||
|
||||
// Address implements SDK PubKey interface.
|
||||
func (m *PubKey) Address() tmcrypto.Address {
|
||||
return m.Key.Address(proto.MessageName(m))
|
||||
}
|
||||
|
||||
// Type returns key type name. Implements SDK PubKey interface.
|
||||
func (m *PubKey) Type() string {
|
||||
return name
|
||||
}
|
||||
|
||||
// VerifySignature implements SDK PubKey interface.
|
||||
func (m *PubKey) VerifySignature(msg []byte, sig []byte) bool {
|
||||
return m.Key.VerifySignature(msg, sig)
|
||||
}
|
||||
|
||||
type ecdsaPK struct {
|
||||
ecdsa.PubKey
|
||||
}
|
||||
|
||||
// Size implements proto.Marshaler interface
|
||||
func (pk *ecdsaPK) Size() int {
|
||||
if pk == nil {
|
||||
return 0
|
||||
}
|
||||
return pubKeySize
|
||||
}
|
||||
|
||||
// Unmarshal implements proto.Marshaler interface
|
||||
func (pk *ecdsaPK) Unmarshal(bz []byte) error {
|
||||
return pk.PubKey.Unmarshal(bz, secp256r1, pubKeySize)
|
||||
}
|
||||
118
crypto/keys/secp256r1/pubkey_internal_test.go
Normal file
118
crypto/keys/secp256r1/pubkey_internal_test.go
Normal file
@ -0,0 +1,118 @@
|
||||
package secp256r1
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/codec/types"
|
||||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
)
|
||||
|
||||
var _ cryptotypes.PubKey = (*PubKey)(nil)
|
||||
|
||||
func TestPKSuite(t *testing.T) {
|
||||
suite.Run(t, new(PKSuite))
|
||||
}
|
||||
|
||||
type CommonSuite struct {
|
||||
suite.Suite
|
||||
pk *PubKey // cryptotypes.PubKey
|
||||
sk cryptotypes.PrivKey
|
||||
}
|
||||
|
||||
func (suite *CommonSuite) SetupSuite() {
|
||||
sk, err := GenPrivKey()
|
||||
suite.Require().NoError(err)
|
||||
suite.sk = sk
|
||||
suite.pk = sk.PubKey().(*PubKey)
|
||||
}
|
||||
|
||||
type PKSuite struct{ CommonSuite }
|
||||
|
||||
func (suite *PKSuite) TestString() {
|
||||
require := suite.Require()
|
||||
|
||||
pkStr := suite.pk.String()
|
||||
prefix := "secp256r1{"
|
||||
require.Equal(prefix, pkStr[:len(prefix)])
|
||||
}
|
||||
|
||||
func (suite *PKSuite) TestType() {
|
||||
suite.Require().Equal(name, suite.pk.Type())
|
||||
}
|
||||
|
||||
func (suite *PKSuite) TestEquals() {
|
||||
require := suite.Require()
|
||||
|
||||
skOther, err := GenPrivKey()
|
||||
require.NoError(err)
|
||||
pkOther := skOther.PubKey()
|
||||
pkOther2 := &PubKey{&ecdsaPK{skOther.Secret.PubKey()}}
|
||||
|
||||
require.False(suite.pk.Equals(pkOther))
|
||||
require.True(pkOther.Equals(pkOther2))
|
||||
require.True(pkOther2.Equals(pkOther))
|
||||
require.True(pkOther.Equals(pkOther), "Equals must be reflexive")
|
||||
}
|
||||
|
||||
func (suite *PKSuite) TestMarshalProto() {
|
||||
require := suite.Require()
|
||||
|
||||
/**** test structure marshalling ****/
|
||||
|
||||
var pk PubKey
|
||||
bz, err := proto.Marshal(suite.pk)
|
||||
require.NoError(err)
|
||||
require.NoError(proto.Unmarshal(bz, &pk))
|
||||
require.True(pk.Equals(suite.pk))
|
||||
|
||||
/**** test structure marshalling with codec ****/
|
||||
|
||||
pk = PubKey{}
|
||||
registry := types.NewInterfaceRegistry()
|
||||
cdc := codec.NewProtoCodec(registry)
|
||||
bz, err = cdc.MarshalBinaryBare(suite.pk)
|
||||
require.NoError(err)
|
||||
require.NoError(cdc.UnmarshalBinaryBare(bz, &pk))
|
||||
require.True(pk.Equals(suite.pk))
|
||||
|
||||
const bufSize = 100
|
||||
bz2 := make([]byte, bufSize)
|
||||
pkCpy := suite.pk
|
||||
_, err = pkCpy.MarshalTo(bz2)
|
||||
require.NoError(err)
|
||||
require.Len(bz2, bufSize)
|
||||
require.Equal(bz, bz2[:pk.Size()])
|
||||
|
||||
bz2 = make([]byte, bufSize)
|
||||
_, err = pkCpy.MarshalToSizedBuffer(bz2)
|
||||
require.NoError(err)
|
||||
require.Len(bz2, bufSize)
|
||||
require.Equal(bz, bz2[(bufSize-pk.Size()):])
|
||||
|
||||
/**** test interface marshalling ****/
|
||||
bz, err = cdc.MarshalInterface(suite.pk)
|
||||
require.NoError(err)
|
||||
var pkI cryptotypes.PubKey
|
||||
err = cdc.UnmarshalInterface(bz, &pkI)
|
||||
require.EqualError(err, "no registered implementations of type types.PubKey")
|
||||
|
||||
RegisterInterfaces(registry)
|
||||
require.NoError(cdc.UnmarshalInterface(bz, &pkI))
|
||||
require.True(pkI.Equals(suite.pk))
|
||||
|
||||
cdc.UnmarshalInterface(bz, nil)
|
||||
require.Error(err, "nil should fail")
|
||||
}
|
||||
|
||||
func (suite *PKSuite) TestSize() {
|
||||
require := suite.Require()
|
||||
var pk ecdsaPK
|
||||
require.Equal(pk.Size(), len(suite.pk.Bytes()))
|
||||
|
||||
var nilPk *ecdsaPK
|
||||
require.Equal(0, nilPk.Size(), "nil value must have zero size")
|
||||
}
|
||||
@ -190,6 +190,10 @@
|
||||
- [PrivKey](#cosmos.crypto.secp256k1.PrivKey)
|
||||
- [PubKey](#cosmos.crypto.secp256k1.PubKey)
|
||||
|
||||
- [cosmos/crypto/secp256r1/keys.proto](#cosmos/crypto/secp256r1/keys.proto)
|
||||
- [PrivKey](#cosmos.crypto.secp256r1.PrivKey)
|
||||
- [PubKey](#cosmos.crypto.secp256r1.PubKey)
|
||||
|
||||
- [cosmos/distribution/v1beta1/distribution.proto](#cosmos/distribution/v1beta1/distribution.proto)
|
||||
- [CommunityPoolSpendProposal](#cosmos.distribution.v1beta1.CommunityPoolSpendProposal)
|
||||
- [CommunityPoolSpendProposalWithDeposit](#cosmos.distribution.v1beta1.CommunityPoolSpendProposalWithDeposit)
|
||||
@ -3115,6 +3119,52 @@ This prefix is followed with the x-coordinate.
|
||||
|
||||
|
||||
|
||||
<!-- end messages -->
|
||||
|
||||
<!-- end enums -->
|
||||
|
||||
<!-- end HasExtensions -->
|
||||
|
||||
<!-- end services -->
|
||||
|
||||
|
||||
|
||||
<a name="cosmos/crypto/secp256r1/keys.proto"></a>
|
||||
<p align="right"><a href="#top">Top</a></p>
|
||||
|
||||
## cosmos/crypto/secp256r1/keys.proto
|
||||
|
||||
|
||||
|
||||
<a name="cosmos.crypto.secp256r1.PrivKey"></a>
|
||||
|
||||
### PrivKey
|
||||
PrivKey defines a secp256r1 ECDSA private key.
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| `secret` | [bytes](#bytes) | | secret number serialized using big-endian encoding |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name="cosmos.crypto.secp256r1.PubKey"></a>
|
||||
|
||||
### PubKey
|
||||
PubKey defines a secp256r1 ECDSA public key.
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| `key` | [bytes](#bytes) | | Point on secp256r1 curve in a compressed representation as specified in section 4.3.6 of ANSI X9.62. |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- end messages -->
|
||||
|
||||
<!-- end enums -->
|
||||
|
||||
22
proto/cosmos/crypto/secp256r1/keys.proto
Normal file
22
proto/cosmos/crypto/secp256r1/keys.proto
Normal file
@ -0,0 +1,22 @@
|
||||
syntax = "proto3";
|
||||
package cosmos.crypto.secp256r1;
|
||||
|
||||
import "gogoproto/gogo.proto";
|
||||
|
||||
option go_package = "github.com/cosmos/cosmos-sdk/crypto/keys/secp256r1";
|
||||
option (gogoproto.messagename_all) = true;
|
||||
option (gogoproto.goproto_stringer_all) = false;
|
||||
option (gogoproto.goproto_getters_all) = false;
|
||||
|
||||
// PubKey defines a secp256r1 ECDSA public key.
|
||||
message PubKey {
|
||||
// Point on secp256r1 curve in a compressed representation as specified in section
|
||||
// 4.3.6 of ANSI X9.62: https://webstore.ansi.org/standards/ascx9/ansix9621998
|
||||
bytes key = 1 [(gogoproto.customtype) = "ecdsaPK"];
|
||||
}
|
||||
|
||||
// PrivKey defines a secp256r1 ECDSA private key.
|
||||
message PrivKey {
|
||||
// secret number serialized using big-endian encoding
|
||||
bytes secret = 1 [(gogoproto.customtype) = "ecdsaSK"];
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user