Skip to content

Commit

Permalink
Merge pull request #63 from coinbase/patrick/misc-fixes
Browse files Browse the repository at this point in the history
Miscellaneous Fixes Before Release
  • Loading branch information
patrick-ogrady authored Jul 13, 2020
2 parents 6f86031 + 3089bc4 commit 6fcf086
Show file tree
Hide file tree
Showing 10 changed files with 87 additions and 101 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@ generated from the [rosetta-specifications](https://github.com/coinbase/rosetta-
Before diving into the SDK, we recommend taking a look at the Rosetta API Docs:

* [Overview](https://www.rosetta-api.org/docs/welcome.html)
* [Node API](https://www.rosetta-api.org/docs/node_api_introduction.html)
* [Wallet API (coming soon!)](https://www.rosetta-api.org/docs/wallet_api_introduction.html)
* [Data API](https://www.rosetta-api.org/docs/data_api_introduction.html)
* [Construction API](https://www.rosetta-api.org/docs/construction_api_introduction.html)

## Packages
* [Types](types): Auto-generated Rosetta types
* [Client](client): Low-level communication with any Rosetta server
* [Server](server): Simplified Rosetta Node API server development
* [Server](server): Simplified Rosetta API server development
* [Asserter](asserter): Validation of Rosetta types
* [Fetcher](fetcher): Simplified and validated communication with
any Rosetta server
Expand Down
62 changes: 24 additions & 38 deletions keys/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ const PrivKeyBytesLen = 32

// GenerateKeypair returns a Keypair of a specified CurveType
func GenerateKeypair(curve types.CurveType) (*KeyPair, error) {
var keyPair *KeyPair

switch curve {
case types.Secp256k1:
rawPrivKey, err := btcec.NewPrivateKey(btcec.S256())
Expand All @@ -43,16 +41,13 @@ func GenerateKeypair(curve types.CurveType) (*KeyPair, error) {
Bytes: rawPubKey.SerializeCompressed(),
CurveType: curve,
}
privKey := &PrivateKey{
Bytes: rawPrivKey.Serialize(),
CurveType: curve,
}

keyPair = &KeyPair{
keyPair := &KeyPair{
PublicKey: pubKey,
PrivateKey: privKey,
PrivateKey: rawPrivKey.Serialize(),
}

return keyPair, nil
case types.Edwards25519:
rawPubKey, rawPrivKey, err := ed25519.GenerateKey(nil)
if err != nil {
Expand All @@ -64,54 +59,45 @@ func GenerateKeypair(curve types.CurveType) (*KeyPair, error) {
CurveType: curve,
}

privKey := &PrivateKey{
Bytes: rawPrivKey.Seed(),
CurveType: curve,
}

keyPair = &KeyPair{
keyPair := &KeyPair{
PublicKey: pubKey,
PrivateKey: privKey,
PrivateKey: rawPrivKey.Seed(),
}

return keyPair, nil
default:
return nil, fmt.Errorf("%s is not supported", curve)
}

return keyPair, nil
}

// IsValid checks the validity of a keypair
func (k *KeyPair) IsValid() error {
sk := k.PrivateKey.Bytes
pkCurve := k.PublicKey.CurveType
skCurve := k.PrivateKey.CurveType

// Checks if valid Public Key
// Checks if valid PublicKey and CurveType
err := asserter.PublicKey(k.PublicKey)
if err != nil {
return err
}

// Checks if valid CurveType
err = asserter.CurveType(pkCurve)
if err != nil {
return err
}

// Checks if pk and sk have the same CurveType
if pkCurve != skCurve {
// Will change if we support more CurveTypes with different privkey sizes
if len(k.PrivateKey) != PrivKeyBytesLen {
return fmt.Errorf(
"private key curve %s and public key curve %s do not match",
skCurve,
pkCurve,
"invalid privkey length %v. Expected 32 bytes",
len(k.PrivateKey),
)
}

// Will change if we support more CurveTypes with different privkey sizes
if len(sk) != PrivKeyBytesLen {
return fmt.Errorf("invalid privkey length %v. Expected 32 bytes", len(sk))
}

return nil
}

// Signer returns the constructs a Signer
// for the KeyPair.
func (k *KeyPair) Signer() (Signer, error) {
switch k.PublicKey.CurveType {
case types.Secp256k1:
return &SignerSecp256k1{k}, nil
case types.Edwards25519:
return &SignerEdwards25519{k}, nil
default:
return nil, fmt.Errorf("curve %s not supported", k.PublicKey.CurveType)
}
}
35 changes: 20 additions & 15 deletions keys/keys_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,24 +25,27 @@ import (
)

func TestJSONEncoding(t *testing.T) {
secpKeypair, _ := GenerateKeypair(types.Secp256k1)
ed25519Keypair, _ := GenerateKeypair(types.Secp256k1)
secp256k1Keypair, err := GenerateKeypair(types.Secp256k1)
assert.NoError(t, err)

edwards25519Keypair, err := GenerateKeypair(types.Edwards25519)
assert.NoError(t, err)

var keyPairs = []*KeyPair{secpKeypair, ed25519Keypair}
var keyPairs = []*KeyPair{secp256k1Keypair, edwards25519Keypair}
for _, keypair := range keyPairs {
privKeyJSON, err := json.Marshal(keypair.PrivateKey)
kpb, err := json.Marshal(keypair)
assert.NoError(t, err)

// Simple Hex Check
simpleType := struct {
HexBytes string `json:"hex_bytes"`
HexBytes string `json:"private_key"`
}{}
err = json.Unmarshal(privKeyJSON, &simpleType)
err = json.Unmarshal(kpb, &simpleType)
assert.NoError(t, err)

b, err := hex.DecodeString(simpleType.HexBytes)
assert.NoError(t, err)
assert.Equal(t, keypair.PrivateKey.Bytes, b)
assert.Equal(t, keypair.PrivateKey, b)
}
}

Expand All @@ -52,7 +55,7 @@ func TestGenerateKeypairSecp256k1(t *testing.T) {

assert.NoError(t, err)
assert.Equal(t, keypair.PublicKey.CurveType, curve)
assert.Equal(t, keypair.PrivateKey.CurveType, curve)
assert.Len(t, keypair.PrivateKey, PrivKeyBytesLen)
}

func TestGenerateKeypairEdwards25519(t *testing.T) {
Expand All @@ -61,21 +64,23 @@ func TestGenerateKeypairEdwards25519(t *testing.T) {

assert.NoError(t, err)
assert.Equal(t, keypair.PublicKey.CurveType, curve)
assert.Equal(t, keypair.PrivateKey.CurveType, curve)
assert.Len(t, keypair.PrivateKey, PrivKeyBytesLen)
}

func mockKeyPair(privKey []byte, curveType types.CurveType) *KeyPair {
keypair, _ := GenerateKeypair(curveType)
keypair.PrivateKey.Bytes = privKey
keypair.PrivateKey = privKey
return keypair
}

func TestKeypairValidity(t *testing.T) {
// Non matching curves
keyPair, _ := GenerateKeypair(types.Edwards25519)
keyPair.PublicKey.CurveType = types.Secp256k1
err := keyPair.IsValid()
assert.Contains(t, err.Error(), "do not match")
// invalid CurveType
keyPair, err := GenerateKeypair(types.Edwards25519)
assert.NoError(t, err)

keyPair.PublicKey.CurveType = "blah"
err = keyPair.IsValid()
assert.Contains(t, err.Error(), "blah is not a supported CurveType")

type privKeyTest struct {
keypair *KeyPair
Expand Down
16 changes: 8 additions & 8 deletions keys/signer_ed25519.go → keys/signer_edwards25519.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,20 @@ import (
"github.com/coinbase/rosetta-sdk-go/types"
)

// SignerEd25519 is initialized from a keypair
type SignerEd25519 struct {
// SignerEdwards25519 is initialized from a keypair
type SignerEdwards25519 struct {
KeyPair *KeyPair
}

var _ Signer = (*SignerEd25519)(nil)
var _ Signer = (*SignerEdwards25519)(nil)

// PublicKey returns the PublicKey of the signer
func (s *SignerEd25519) PublicKey() *types.PublicKey {
func (s *SignerEdwards25519) PublicKey() *types.PublicKey {
return s.KeyPair.PublicKey
}

// Signs arbitrary payloads using a KeyPair
func (s *SignerEd25519) Sign(
// Sign arbitrary payloads using a KeyPair
func (s *SignerEdwards25519) Sign(
payload *types.SigningPayload,
sigType types.SignatureType,
) (*types.Signature, error) {
Expand All @@ -53,7 +53,7 @@ func (s *SignerEd25519) Sign(
return nil, fmt.Errorf("sign: signature type is not %v", types.Ed25519)
}

privKeyBytes := s.KeyPair.PrivateKey.Bytes
privKeyBytes := s.KeyPair.PrivateKey
privKey := ed25519.NewKeyFromSeed(privKeyBytes)
sig := ed25519.Sign(privKey, payload.Bytes)

Expand All @@ -67,7 +67,7 @@ func (s *SignerEd25519) Sign(

// Verify verifies a Signature, by checking the validity of a Signature,
// the SigningPayload, and the PublicKey of the Signature.
func (s *SignerEd25519) Verify(signature *types.Signature) error {
func (s *SignerEdwards25519) Verify(signature *types.Signature) error {
if signature.SignatureType != types.Ed25519 {
return fmt.Errorf("verify: payload signature type is not %v", types.Ed25519)
}
Expand Down
25 changes: 13 additions & 12 deletions keys/signer_ed25519_test.go → keys/signer_edwards25519_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ import (
"github.com/stretchr/testify/assert"
)

var signerEd25519 Signer
var signerEdwards25519 Signer

func init() {
keypair, _ := GenerateKeypair(types.Edwards25519)
signerEd25519 = &SignerEd25519{keypair}
signerEdwards25519, _ = keypair.Signer()
}

func mockPayload(msg []byte, signatureType types.SignatureType) *types.SigningPayload {
Expand All @@ -39,7 +39,7 @@ func mockPayload(msg []byte, signatureType types.SignatureType) *types.SigningPa
return payload
}

func TestSignEd25519(t *testing.T) {
func TestSignEdwards25519(t *testing.T) {
type payloadTest struct {
payload *types.SigningPayload
err bool
Expand All @@ -54,7 +54,7 @@ func TestSignEd25519(t *testing.T) {
}

for _, test := range payloadTests {
signature, err := signerEd25519.Sign(test.payload, types.Ed25519)
signature, err := signerEdwards25519.Sign(test.payload, types.Ed25519)

if !test.err {
assert.NoError(t, err)
Expand Down Expand Up @@ -85,7 +85,7 @@ func mockSignature(
return mockSig
}

func TestVerifyEd25519(t *testing.T) {
func TestVerifyEdwards25519(t *testing.T) {
type signatureTest struct {
signature *types.Signature
errMsg string
Expand All @@ -96,36 +96,37 @@ func TestVerifyEd25519(t *testing.T) {
Bytes: make([]byte, 32),
SignatureType: types.Ed25519,
}
testSignature, _ := signerEd25519.Sign(payload, types.Ed25519)
testSignature, err := signerEdwards25519.Sign(payload, types.Ed25519)
assert.NoError(t, err)

var signatureTests = []signatureTest{
{mockSignature(
types.Ecdsa,
signerEd25519.PublicKey(),
signerEdwards25519.PublicKey(),
make([]byte, 32),
make([]byte, 32)), "payload signature type is not ed25519"},
{mockSignature(
types.EcdsaRecovery,
signerEd25519.PublicKey(),
signerEdwards25519.PublicKey(),
make([]byte, 32),
make([]byte, 32)), "payload signature type is not ed25519"},
{mockSignature(
types.Ed25519,
signerEd25519.PublicKey(),
signerEdwards25519.PublicKey(),
make([]byte, 40),
testSignature.Bytes), "verify returned false"},
}

for _, test := range signatureTests {
err := signerEd25519.Verify(test.signature)
err := signerEdwards25519.Verify(test.signature)
assert.Contains(t, err.Error(), test.errMsg)
}

goodSignature := mockSignature(
types.Ed25519,
signerEd25519.PublicKey(),
signerEdwards25519.PublicKey(),
make([]byte, 32),
testSignature.Bytes,
)
assert.Equal(t, nil, signerEd25519.Verify(goodSignature))
assert.Equal(t, nil, signerEdwards25519.Verify(goodSignature))
}
4 changes: 2 additions & 2 deletions keys/signer_secp256k1.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func (s *SignerSecp256k1) PublicKey() *types.PublicKey {
return s.KeyPair.PublicKey
}

// Signs arbitrary payloads using a KeyPair
// Sign arbitrary payloads using a KeyPair
func (s *SignerSecp256k1) Sign(
payload *types.SigningPayload,
sigType types.SignatureType,
Expand All @@ -48,7 +48,7 @@ func (s *SignerSecp256k1) Sign(
if err != nil {
return nil, err
}
privKeyBytes := s.KeyPair.PrivateKey.Bytes
privKeyBytes := s.KeyPair.PrivateKey

if !(payload.SignatureType == sigType || payload.SignatureType == "") {
return nil, fmt.Errorf("sign: invalid payload signaturetype %v", payload.SignatureType)
Expand Down
2 changes: 1 addition & 1 deletion keys/signer_secp256k1_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ var signerSecp256k1 Signer

func init() {
keypair, _ := GenerateKeypair(types.Secp256k1)
signerSecp256k1 = &SignerSecp256k1{keypair}
signerSecp256k1, _ = keypair.Signer()
}

func TestSignSecp256k1(t *testing.T) {
Expand Down
Loading

0 comments on commit 6fcf086

Please sign in to comment.