From e6d35ee6416f0e234ae39ce01aab5922b7ff3b5d Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Wed, 22 Feb 2017 23:15:10 +0100 Subject: [PATCH 1/7] Add structs for go-data support --- Makefile | 9 +++++++++ priv_key.go | 56 ++++++++++++++++++++++++++++++++++++++++++++++------ pub_key.go | 56 ++++++++++++++++++++++++++++++++++++++++++++++------ signature.go | 47 ++++++++++++++++++++++++++++++++++++------- 4 files changed, 149 insertions(+), 19 deletions(-) create mode 100644 Makefile diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..0cd05448a --- /dev/null +++ b/Makefile @@ -0,0 +1,9 @@ +.PHONY: docs +REPO:=github.com/tendermint/go-crypto + +docs: + @go get github.com/davecheney/godoc2md + godoc2md $(REPO) > README.md + +test: + go test ./... diff --git a/priv_key.go b/priv_key.go index 8b7dc117f..ac4760c7c 100644 --- a/priv_key.go +++ b/priv_key.go @@ -7,6 +7,7 @@ import ( "github.com/tendermint/ed25519" "github.com/tendermint/ed25519/extra25519" . "github.com/tendermint/go-common" + data "github.com/tendermint/go-data" "github.com/tendermint/go-wire" ) @@ -22,14 +23,35 @@ type PrivKey interface { const ( PrivKeyTypeEd25519 = byte(0x01) PrivKeyTypeSecp256k1 = byte(0x02) + PrivKeyNameEd25519 = "ed25519" + PrivKeyNameSecp256k1 = "secp256k1" ) -// for wire.readReflect -var _ = wire.RegisterInterface( - struct{ PrivKey }{}, - wire.ConcreteType{PrivKeyEd25519{}, PrivKeyTypeEd25519}, - wire.ConcreteType{PrivKeySecp256k1{}, PrivKeyTypeSecp256k1}, -) +var privKeyMapper data.Mapper + +// register both private key types with go-data (and thus go-wire) +func init() { + privKeyMapper = data.NewMapper(PrivKeyS{}). + RegisterInterface(PrivKeyEd25519{}, PrivKeyNameEd25519, PrivKeyTypeEd25519). + RegisterInterface(PrivKeySecp256k1{}, PrivKeyNameSecp256k1, PrivKeyTypeSecp256k1) +} + +// PrivKeyS add json serialization to PrivKey +type PrivKeyS struct { + PrivKey +} + +func (p PrivKeyS) MarshalJSON() ([]byte, error) { + return privKeyMapper.ToJSON(p.PrivKey) +} + +func (p *PrivKeyS) UnmarshalJSON(data []byte) (err error) { + parsed, err := privKeyMapper.FromJSON(data) + if err == nil { + p.PrivKey = parsed.(PrivKey) + } + return +} func PrivKeyFromBytes(privKeyBytes []byte) (privKey PrivKey, err error) { err = wire.ReadBinaryBytes(privKeyBytes, &privKey) @@ -64,6 +86,17 @@ func (privKey PrivKeyEd25519) Equals(other PrivKey) bool { } } +func (p PrivKeyEd25519) MarshalJSON() ([]byte, error) { + return data.Encoder.Marshal(p[:]) +} + +func (p *PrivKeyEd25519) UnmarshalJSON(enc []byte) error { + var ref []byte + err := data.Encoder.Unmarshal(&ref, enc) + copy(p[:], ref) + return err +} + func (privKey PrivKeyEd25519) ToCurve25519() *[32]byte { keyCurve25519 := new([32]byte) privKeyBytes := [64]byte(privKey) @@ -136,6 +169,17 @@ func (privKey PrivKeySecp256k1) Equals(other PrivKey) bool { } } +func (p PrivKeySecp256k1) MarshalJSON() ([]byte, error) { + return data.Encoder.Marshal(p[:]) +} + +func (p *PrivKeySecp256k1) UnmarshalJSON(enc []byte) error { + var ref []byte + err := data.Encoder.Unmarshal(&ref, enc) + copy(p[:], ref) + return err +} + func (privKey PrivKeySecp256k1) String() string { return Fmt("PrivKeySecp256k1{*****}") } diff --git a/pub_key.go b/pub_key.go index a3a259795..54d1173eb 100644 --- a/pub_key.go +++ b/pub_key.go @@ -7,6 +7,7 @@ import ( "github.com/tendermint/ed25519" "github.com/tendermint/ed25519/extra25519" . "github.com/tendermint/go-common" + data "github.com/tendermint/go-data" "github.com/tendermint/go-wire" "golang.org/x/crypto/ripemd160" ) @@ -24,14 +25,35 @@ type PubKey interface { const ( PubKeyTypeEd25519 = byte(0x01) PubKeyTypeSecp256k1 = byte(0x02) + PubKeyNameEd25519 = "ed25519" + PubKeyNameSecp256k1 = "secp256k1" ) -// for wire.readReflect -var _ = wire.RegisterInterface( - struct{ PubKey }{}, - wire.ConcreteType{PubKeyEd25519{}, PubKeyTypeEd25519}, - wire.ConcreteType{PubKeySecp256k1{}, PubKeyTypeSecp256k1}, -) +var pubKeyMapper data.Mapper + +// register both public key types with go-data (and thus go-wire) +func init() { + pubKeyMapper = data.NewMapper(PubKeyS{}). + RegisterInterface(PubKeyEd25519{}, PubKeyNameEd25519, PubKeyTypeEd25519). + RegisterInterface(PubKeySecp256k1{}, PubKeyNameSecp256k1, PubKeyTypeSecp256k1) +} + +// PubKeyS add json serialization to PubKey +type PubKeyS struct { + PubKey +} + +func (p PubKeyS) MarshalJSON() ([]byte, error) { + return pubKeyMapper.ToJSON(p.PubKey) +} + +func (p *PubKeyS) UnmarshalJSON(data []byte) (err error) { + parsed, err := pubKeyMapper.FromJSON(data) + if err == nil { + p.PubKey = parsed.(PubKey) + } + return +} func PubKeyFromBytes(pubKeyBytes []byte) (pubKey PubKey, err error) { err = wire.ReadBinaryBytes(pubKeyBytes, &pubKey) @@ -70,6 +92,17 @@ func (pubKey PubKeyEd25519) VerifyBytes(msg []byte, sig_ Signature) bool { return ed25519.Verify(&pubKeyBytes, msg, &sigBytes) } +func (p PubKeyEd25519) MarshalJSON() ([]byte, error) { + return data.Encoder.Marshal(p[:]) +} + +func (p *PubKeyEd25519) UnmarshalJSON(enc []byte) error { + var ref []byte + err := data.Encoder.Unmarshal(&ref, enc) + copy(p[:], ref) + return err +} + // For use with golang/crypto/nacl/box // If error, returns nil. func (pubKey PubKeyEd25519) ToCurve25519() *[32]byte { @@ -137,6 +170,17 @@ func (pubKey PubKeySecp256k1) VerifyBytes(msg []byte, sig_ Signature) bool { return sig__.Verify(Sha256(msg), pub__) } +func (p PubKeySecp256k1) MarshalJSON() ([]byte, error) { + return data.Encoder.Marshal(p[:]) +} + +func (p *PubKeySecp256k1) UnmarshalJSON(enc []byte) error { + var ref []byte + err := data.Encoder.Unmarshal(&ref, enc) + copy(p[:], ref) + return err +} + func (pubKey PubKeySecp256k1) String() string { return Fmt("PubKeySecp256k1{%X}", pubKey[:]) } diff --git a/signature.go b/signature.go index b0049da8d..3960088bd 100644 --- a/signature.go +++ b/signature.go @@ -5,6 +5,7 @@ import ( "fmt" . "github.com/tendermint/go-common" + data "github.com/tendermint/go-data" "github.com/tendermint/go-wire" ) @@ -20,14 +21,35 @@ type Signature interface { const ( SignatureTypeEd25519 = byte(0x01) SignatureTypeSecp256k1 = byte(0x02) + SignatureNameEd25519 = "ed25519" + SignatureNameSecp256k1 = "secp256k1" ) -// for wire.readReflect -var _ = wire.RegisterInterface( - struct{ Signature }{}, - wire.ConcreteType{SignatureEd25519{}, SignatureTypeEd25519}, - wire.ConcreteType{SignatureSecp256k1{}, SignatureTypeSecp256k1}, -) +var sigMapper data.Mapper + +// register both public key types with go-data (and thus go-wire) +func init() { + sigMapper = data.NewMapper(SignatureS{}). + RegisterInterface(SignatureEd25519{}, SignatureNameEd25519, SignatureTypeEd25519). + RegisterInterface(SignatureSecp256k1{}, SignatureNameSecp256k1, SignatureTypeSecp256k1) +} + +// SignatureS add json serialization to Signature +type SignatureS struct { + Signature +} + +func (p SignatureS) MarshalJSON() ([]byte, error) { + return sigMapper.ToJSON(p.Signature) +} + +func (p *SignatureS) UnmarshalJSON(data []byte) (err error) { + parsed, err := sigMapper.FromJSON(data) + if err == nil { + p.Signature = parsed.(Signature) + } + return +} func SignatureFromBytes(sigBytes []byte) (sig Signature, err error) { err = wire.ReadBinaryBytes(sigBytes, &sig) @@ -55,10 +77,21 @@ func (sig SignatureEd25519) Equals(other Signature) bool { } } +func (p SignatureEd25519) MarshalJSON() ([]byte, error) { + return data.Encoder.Marshal(p[:]) +} + +func (p *SignatureEd25519) UnmarshalJSON(enc []byte) error { + var ref []byte + err := data.Encoder.Unmarshal(&ref, enc) + copy(p[:], ref) + return err +} + //------------------------------------- // Implements Signature -type SignatureSecp256k1 []byte +type SignatureSecp256k1 data.Bytes func (sig SignatureSecp256k1) Bytes() []byte { return wire.BinaryBytes(struct{ Signature }{sig}) From 1bc1947e3f94e628778a38d36256bce8a66a6779 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Wed, 22 Feb 2017 23:43:26 +0100 Subject: [PATCH 2/7] First tests of go-data encoding --- pub_key.go | 17 +++++-- signature.go | 9 +++- signature_test.go | 121 ++++++++++++++++++++++------------------------ 3 files changed, 80 insertions(+), 67 deletions(-) diff --git a/pub_key.go b/pub_key.go index 54d1173eb..0c7f4663e 100644 --- a/pub_key.go +++ b/pub_key.go @@ -83,6 +83,11 @@ func (pubKey PubKeyEd25519) Bytes() []byte { } func (pubKey PubKeyEd25519) VerifyBytes(msg []byte, sig_ Signature) bool { + // unwrap if needed + if wrap, ok := sig_.(SignatureS); ok { + sig_ = wrap.Signature + } + // make sure we use the same algorithm to sign sig, ok := sig_.(SignatureEd25519) if !ok { return false @@ -155,14 +160,20 @@ func (pubKey PubKeySecp256k1) Bytes() []byte { } func (pubKey PubKeySecp256k1) VerifyBytes(msg []byte, sig_ Signature) bool { - pub__, err := secp256k1.ParsePubKey(append([]byte{0x04}, pubKey[:]...), secp256k1.S256()) - if err != nil { - return false + // unwrap if needed + if wrap, ok := sig_.(SignatureS); ok { + sig_ = wrap.Signature } + // and assert same algorithm to sign and verify sig, ok := sig_.(SignatureSecp256k1) if !ok { return false } + + pub__, err := secp256k1.ParsePubKey(append([]byte{0x04}, pubKey[:]...), secp256k1.S256()) + if err != nil { + return false + } sig__, err := secp256k1.ParseDERSignature(sig[:], secp256k1.S256()) if err != nil { return false diff --git a/signature.go b/signature.go index 3960088bd..fcef20a43 100644 --- a/signature.go +++ b/signature.go @@ -91,7 +91,7 @@ func (p *SignatureEd25519) UnmarshalJSON(enc []byte) error { //------------------------------------- // Implements Signature -type SignatureSecp256k1 data.Bytes +type SignatureSecp256k1 []byte func (sig SignatureSecp256k1) Bytes() []byte { return wire.BinaryBytes(struct{ Signature }{sig}) @@ -108,3 +108,10 @@ func (sig SignatureSecp256k1) Equals(other Signature) bool { return false } } +func (p SignatureSecp256k1) MarshalJSON() ([]byte, error) { + return data.Encoder.Marshal(p) +} + +func (p *SignatureSecp256k1) UnmarshalJSON(enc []byte) error { + return data.Encoder.Unmarshal((*[]byte)(p), enc) +} diff --git a/signature_test.go b/signature_test.go index 88c490f39..ac631eac5 100644 --- a/signature_test.go +++ b/signature_test.go @@ -1,11 +1,14 @@ package crypto import ( - "bytes" + "fmt" + "strings" "testing" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/tendermint/ed25519" - "github.com/tendermint/go-wire" + data "github.com/tendermint/go-data" ) func TestSignAndValidateEd25519(t *testing.T) { @@ -56,68 +59,60 @@ func TestSignAndValidateSecp256k1(t *testing.T) { } } -func TestBinaryDecodeEd25519(t *testing.T) { - - privKey := GenPrivKeyEd25519() - pubKey := privKey.PubKey() - - msg := CRandBytes(128) - sig := privKey.Sign(msg) - t.Logf("msg: %X, sig: %X", msg, sig) - - buf, n, err := new(bytes.Buffer), new(int), new(error) - wire.WriteBinary(struct{ Signature }{sig}, buf, n, err) - if *err != nil { - t.Fatalf("Failed to write Signature: %v", err) - } - - if len(buf.Bytes()) != ed25519.SignatureSize+1 { - // 1 byte TypeByte, 64 bytes signature bytes - t.Fatalf("Unexpected signature write size: %v", len(buf.Bytes())) - } - if buf.Bytes()[0] != SignatureTypeEd25519 { - t.Fatalf("Unexpected signature type byte") - } - - sigStruct := struct{ Signature }{} - sig2 := wire.ReadBinary(sigStruct, buf, 0, n, err) - if *err != nil { - t.Fatalf("Failed to read Signature: %v", err) - } - - // Test the signature - if !pubKey.VerifyBytes(msg, sig2.(struct{ Signature }).Signature.(SignatureEd25519)) { - t.Errorf("Account message signature verification failed") +func TestSignatureEncodings(t *testing.T) { + cases := []struct { + privKey PrivKeyS + sigSize int + sigType byte + sigName string + }{ + { + privKey: PrivKeyS{GenPrivKeyEd25519()}, + sigSize: ed25519.SignatureSize, + sigType: SignatureTypeEd25519, + sigName: SignatureNameEd25519, + }, + { + privKey: PrivKeyS{GenPrivKeySecp256k1()}, + sigSize: 0, // unknown + sigType: SignatureTypeSecp256k1, + sigName: SignatureNameSecp256k1, + }, } -} - -func TestBinaryDecodeSecp256k1(t *testing.T) { - - privKey := GenPrivKeySecp256k1() - pubKey := privKey.PubKey() - - msg := CRandBytes(128) - sig := privKey.Sign(msg) - t.Logf("msg: %X, sig: %X", msg, sig) - buf, n, err := new(bytes.Buffer), new(int), new(error) - wire.WriteBinary(struct{ Signature }{sig}, buf, n, err) - if *err != nil { - t.Fatalf("Failed to write Signature: %v", err) - } - - if buf.Bytes()[0] != SignatureTypeSecp256k1 { - t.Fatalf("Unexpected signature type byte") - } - - sigStruct := struct{ Signature }{} - sig2 := wire.ReadBinary(sigStruct, buf, 0, n, err) - if *err != nil { - t.Fatalf("Failed to read Signature: %v", err) - } - - // Test the signature - if !pubKey.VerifyBytes(msg, sig2.(struct{ Signature }).Signature.(SignatureSecp256k1)) { - t.Errorf("Account message signature verification failed") + for _, tc := range cases { + // note we embed them from the beginning.... + pubKey := PubKeyS{tc.privKey.PubKey()} + + msg := CRandBytes(128) + sig := SignatureS{tc.privKey.Sign(msg)} + + // store as wire + bin, err := data.ToWire(sig) + require.Nil(t, err, "%+v", err) + if tc.sigSize != 0 { + assert.Equal(t, tc.sigSize+1, len(bin)) + } + assert.Equal(t, tc.sigType, bin[0]) + + // and back + sig2 := SignatureS{} + err = data.FromWire(bin, &sig2) + require.Nil(t, err, "%+v", err) + assert.EqualValues(t, sig, sig2) + assert.True(t, pubKey.VerifyBytes(msg, sig2)) + + // store as json + js, err := data.ToJSON(sig) + require.Nil(t, err, "%+v", err) + assert.True(t, strings.Contains(string(js), tc.sigName)) + fmt.Println(string(js)) + + // and back + sig3 := SignatureS{} + err = data.FromJSON(js, &sig3) + require.Nil(t, err, "%+v", err) + assert.EqualValues(t, sig, sig3) + assert.True(t, pubKey.VerifyBytes(msg, sig3)) } } From 6c2bf8c24bcccbe4093b5cfb7fbe54427a527027 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 23 Feb 2017 13:20:30 +0100 Subject: [PATCH 3/7] Clean up test cases -> testify --- armor_test.go | 17 ++++++----------- signature_test.go | 27 +++++++++------------------ symmetric_test.go | 24 +++++++----------------- 3 files changed, 22 insertions(+), 46 deletions(-) diff --git a/armor_test.go b/armor_test.go index 3de37d7bc..5eae87c00 100644 --- a/armor_test.go +++ b/armor_test.go @@ -1,25 +1,20 @@ package crypto import ( - "bytes" "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestSimpleArmor(t *testing.T) { blockType := "MINT TEST" data := []byte("somedata") armorStr := EncodeArmor(blockType, nil, data) - t.Log("Got armor: ", armorStr) // Decode armorStr and test for equivalence. blockType2, _, data2, err := DecodeArmor(armorStr) - if err != nil { - t.Error(err) - } - if blockType != blockType2 { - t.Errorf("Expected block type %v but got %v", blockType, blockType2) - } - if !bytes.Equal(data, data2) { - t.Errorf("Expected data %X but got %X", data2, data) - } + require.Nil(t, err, "%+v", err) + assert.Equal(t, blockType, blockType2) + assert.Equal(t, data, data2) } diff --git a/signature_test.go b/signature_test.go index ac631eac5..e0e30b780 100644 --- a/signature_test.go +++ b/signature_test.go @@ -1,7 +1,6 @@ package crypto import ( - "fmt" "strings" "testing" @@ -18,45 +17,33 @@ func TestSignAndValidateEd25519(t *testing.T) { msg := CRandBytes(128) sig := privKey.Sign(msg) - t.Logf("msg: %X, sig: %X", msg, sig) // Test the signature - if !pubKey.VerifyBytes(msg, sig) { - t.Errorf("Account message signature verification failed") - } + assert.True(t, pubKey.VerifyBytes(msg, sig)) // Mutate the signature, just one bit. sigEd := sig.(SignatureEd25519) sigEd[0] ^= byte(0x01) sig = Signature(sigEd) - if pubKey.VerifyBytes(msg, sig) { - t.Errorf("Account message signature verification should have failed but passed instead") - } + assert.False(t, pubKey.VerifyBytes(msg, sig)) } func TestSignAndValidateSecp256k1(t *testing.T) { - privKey := GenPrivKeySecp256k1() pubKey := privKey.PubKey() msg := CRandBytes(128) sig := privKey.Sign(msg) - t.Logf("msg: %X, sig: %X", msg, sig) - // Test the signature - if !pubKey.VerifyBytes(msg, sig) { - t.Errorf("Account message signature verification failed") - } + assert.True(t, pubKey.VerifyBytes(msg, sig)) // Mutate the signature, just one bit. sigEd := sig.(SignatureSecp256k1) sigEd[0] ^= byte(0x01) sig = Signature(sigEd) - if pubKey.VerifyBytes(msg, sig) { - t.Errorf("Account message signature verification should have failed but passed instead") - } + assert.False(t, pubKey.VerifyBytes(msg, sig)) } func TestSignatureEncodings(t *testing.T) { @@ -106,7 +93,6 @@ func TestSignatureEncodings(t *testing.T) { js, err := data.ToJSON(sig) require.Nil(t, err, "%+v", err) assert.True(t, strings.Contains(string(js), tc.sigName)) - fmt.Println(string(js)) // and back sig3 := SignatureS{} @@ -114,5 +100,10 @@ func TestSignatureEncodings(t *testing.T) { require.Nil(t, err, "%+v", err) assert.EqualValues(t, sig, sig3) assert.True(t, pubKey.VerifyBytes(msg, sig3)) + + // and make sure we can textify it + text, err := data.ToText(sig) + require.Nil(t, err, "%+v", err) + assert.True(t, strings.HasPrefix(text, tc.sigName)) } } diff --git a/symmetric_test.go b/symmetric_test.go index c8134742d..d92bff1aa 100644 --- a/symmetric_test.go +++ b/symmetric_test.go @@ -1,9 +1,11 @@ package crypto import ( - "bytes" "testing" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "golang.org/x/crypto/bcrypt" ) @@ -14,16 +16,10 @@ func TestSimple(t *testing.T) { plaintext := []byte("sometext") secret := []byte("somesecretoflengththirtytwo===32") ciphertext := EncryptSymmetric(plaintext, secret) - plaintext2, err := DecryptSymmetric(ciphertext, secret) - if err != nil { - t.Error(err) - } - - if !bytes.Equal(plaintext, plaintext2) { - t.Errorf("Decrypted plaintext was %X, expected %X", plaintext2, plaintext) - } + require.Nil(t, err, "%+v", err) + assert.Equal(t, plaintext, plaintext2) } func TestSimpleWithKDF(t *testing.T) { @@ -39,14 +35,8 @@ func TestSimpleWithKDF(t *testing.T) { secret = Sha256(secret) ciphertext := EncryptSymmetric(plaintext, secret) - plaintext2, err := DecryptSymmetric(ciphertext, secret) - if err != nil { - t.Error(err) - } - - if !bytes.Equal(plaintext, plaintext2) { - t.Errorf("Decrypted plaintext was %X, expected %X", plaintext2, plaintext) - } + require.Nil(t, err, "%+v", err) + assert.Equal(t, plaintext, plaintext2) } From cbe35e07d1a40dde7245ef926bd47090bba914f7 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 23 Feb 2017 14:56:25 +0100 Subject: [PATCH 4/7] Add more tests for de/en-coding public and private keys --- encode_test.go | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 encode_test.go diff --git a/encode_test.go b/encode_test.go new file mode 100644 index 000000000..224f413c1 --- /dev/null +++ b/encode_test.go @@ -0,0 +1,88 @@ +package crypto + +import ( + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + data "github.com/tendermint/go-data" +) + +type byter interface { + Bytes() []byte +} + +// go to wire encoding and back +func checkWire(t *testing.T, in byter, reader interface{}, typ byte) { + // test to and from binary + bin, err := data.ToWire(in) + require.Nil(t, err, "%+v", err) + assert.Equal(t, typ, bin[0]) + // make sure this is compatible with current (Bytes()) encoding + assert.Equal(t, in.Bytes(), bin) + + err = data.FromWire(bin, reader) + require.Nil(t, err, "%+v", err) +} + +// go to json encoding and back +func checkJSON(t *testing.T, in interface{}, reader interface{}, typ string) { + // test to and from binary + js, err := data.ToJSON(in) + require.Nil(t, err, "%+v", err) + styp := `"` + typ + `"` + assert.True(t, strings.Contains(string(js), styp)) + + err = data.FromJSON(js, reader) + require.Nil(t, err, "%+v", err) + + // also check text format + text, err := data.ToText(in) + require.Nil(t, err, "%+v", err) + parts := strings.Split(text, ":") + require.Equal(t, 2, len(parts)) + // make sure the first part is the typ string + assert.Equal(t, typ, parts[0]) + // and the data is also present in the json + assert.True(t, strings.Contains(string(js), parts[1])) +} + +func TestKeyEncodings(t *testing.T) { + cases := []struct { + privKey PrivKeyS + keyType byte + keyName string + }{ + { + privKey: PrivKeyS{GenPrivKeyEd25519()}, + keyType: PrivKeyTypeEd25519, + keyName: PrivKeyNameEd25519, + }, + { + privKey: PrivKeyS{GenPrivKeySecp256k1()}, + keyType: PrivKeyTypeSecp256k1, + keyName: PrivKeyNameSecp256k1, + }, + } + + for _, tc := range cases { + // check (de/en)codings of private key + priv2 := PrivKeyS{} + checkWire(t, tc.privKey, &priv2, tc.keyType) + assert.EqualValues(t, tc.privKey, priv2) + priv3 := PrivKeyS{} + checkJSON(t, tc.privKey, &priv3, tc.keyName) + assert.EqualValues(t, tc.privKey, priv3) + + // check (de/en)codings of public key + pubKey := PubKeyS{tc.privKey.PubKey()} + pub2 := PubKeyS{} + checkWire(t, pubKey, &pub2, tc.keyType) + assert.EqualValues(t, pubKey, pub2) + pub3 := PubKeyS{} + checkJSON(t, pubKey, &pub3, tc.keyName) + assert.EqualValues(t, pubKey, pub3) + } + +} From b6a2c5949f7ea1d064cbb9dc638eb0a3dca9af34 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 23 Feb 2017 15:35:04 +0100 Subject: [PATCH 5/7] Add helper methods for nil checks in structs --- priv_key.go | 4 ++++ pub_key.go | 4 ++++ signature.go | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/priv_key.go b/priv_key.go index ac4760c7c..60a82636d 100644 --- a/priv_key.go +++ b/priv_key.go @@ -53,6 +53,10 @@ func (p *PrivKeyS) UnmarshalJSON(data []byte) (err error) { return } +func (p PrivKeyS) Empty() bool { + return p.PrivKey == nil +} + func PrivKeyFromBytes(privKeyBytes []byte) (privKey PrivKey, err error) { err = wire.ReadBinaryBytes(privKeyBytes, &privKey) return diff --git a/pub_key.go b/pub_key.go index 0c7f4663e..e5fe5209a 100644 --- a/pub_key.go +++ b/pub_key.go @@ -55,6 +55,10 @@ func (p *PubKeyS) UnmarshalJSON(data []byte) (err error) { return } +func (p PubKeyS) Empty() bool { + return p.PubKey == nil +} + func PubKeyFromBytes(pubKeyBytes []byte) (pubKey PubKey, err error) { err = wire.ReadBinaryBytes(pubKeyBytes, &pubKey) return diff --git a/signature.go b/signature.go index fcef20a43..376a535d6 100644 --- a/signature.go +++ b/signature.go @@ -51,6 +51,10 @@ func (p *SignatureS) UnmarshalJSON(data []byte) (err error) { return } +func (p SignatureS) Empty() bool { + return p.Signature == nil +} + func SignatureFromBytes(sigBytes []byte) (sig Signature, err error) { err = wire.ReadBinaryBytes(sigBytes, &sig) return From 8c9b889ccfe1f891ce8ab36c843f15794ce8f30f Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 23 Feb 2017 18:11:20 +0100 Subject: [PATCH 6/7] Support json encode/decode for nil values in S structs --- encode_test.go | 24 ++++++++++++++++++++++++ priv_key.go | 2 +- pub_key.go | 2 +- signature.go | 2 +- 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/encode_test.go b/encode_test.go index 224f413c1..8f2eebbaa 100644 --- a/encode_test.go +++ b/encode_test.go @@ -84,5 +84,29 @@ func TestKeyEncodings(t *testing.T) { checkJSON(t, pubKey, &pub3, tc.keyName) assert.EqualValues(t, pubKey, pub3) } +} + +func toFromJSON(t *testing.T, in interface{}, recvr interface{}) { + js, err := data.ToJSON(in) + require.Nil(t, err, "%+v", err) + err = data.FromJSON(js, recvr) + require.Nil(t, err, "%+v", err) +} + +func TestNilEncodings(t *testing.T) { + // make sure sigs are okay with nil + a, b := SignatureS{}, SignatureS{} + toFromJSON(t, a, &b) + assert.EqualValues(t, a, b) + + // make sure sigs are okay with nil + c, d := PubKeyS{}, PubKeyS{} + toFromJSON(t, c, &d) + assert.EqualValues(t, c, d) + + // make sure sigs are okay with nil + e, f := PrivKeyS{}, PrivKeyS{} + toFromJSON(t, e, &f) + assert.EqualValues(t, e, f) } diff --git a/priv_key.go b/priv_key.go index 60a82636d..81edfb3f6 100644 --- a/priv_key.go +++ b/priv_key.go @@ -47,7 +47,7 @@ func (p PrivKeyS) MarshalJSON() ([]byte, error) { func (p *PrivKeyS) UnmarshalJSON(data []byte) (err error) { parsed, err := privKeyMapper.FromJSON(data) - if err == nil { + if err == nil && parsed != nil { p.PrivKey = parsed.(PrivKey) } return diff --git a/pub_key.go b/pub_key.go index e5fe5209a..77ce74a97 100644 --- a/pub_key.go +++ b/pub_key.go @@ -49,7 +49,7 @@ func (p PubKeyS) MarshalJSON() ([]byte, error) { func (p *PubKeyS) UnmarshalJSON(data []byte) (err error) { parsed, err := pubKeyMapper.FromJSON(data) - if err == nil { + if err == nil && parsed != nil { p.PubKey = parsed.(PubKey) } return diff --git a/signature.go b/signature.go index 376a535d6..076358879 100644 --- a/signature.go +++ b/signature.go @@ -45,7 +45,7 @@ func (p SignatureS) MarshalJSON() ([]byte, error) { func (p *SignatureS) UnmarshalJSON(data []byte) (err error) { parsed, err := sigMapper.FromJSON(data) - if err == nil { + if err == nil && parsed != nil { p.Signature = parsed.(Signature) } return From 0e92dd5bb557c6530e906e414893f05dda66cf80 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Fri, 24 Feb 2017 00:31:43 +0100 Subject: [PATCH 7/7] One name, type byte per algorithm --- encode_test.go | 8 ++++---- priv_key.go | 14 +++++++------- pub_key.go | 16 ++++------------ signature.go | 12 ++---------- signature_test.go | 8 ++++---- 5 files changed, 21 insertions(+), 37 deletions(-) diff --git a/encode_test.go b/encode_test.go index 8f2eebbaa..977cc64cf 100644 --- a/encode_test.go +++ b/encode_test.go @@ -56,13 +56,13 @@ func TestKeyEncodings(t *testing.T) { }{ { privKey: PrivKeyS{GenPrivKeyEd25519()}, - keyType: PrivKeyTypeEd25519, - keyName: PrivKeyNameEd25519, + keyType: TypeEd25519, + keyName: NameEd25519, }, { privKey: PrivKeyS{GenPrivKeySecp256k1()}, - keyType: PrivKeyTypeSecp256k1, - keyName: PrivKeyNameSecp256k1, + keyType: TypeSecp256k1, + keyName: NameSecp256k1, }, } diff --git a/priv_key.go b/priv_key.go index 81edfb3f6..54fa36a3a 100644 --- a/priv_key.go +++ b/priv_key.go @@ -19,12 +19,12 @@ type PrivKey interface { Equals(PrivKey) bool } -// Types of PrivKey implementations +// Types of implementations const ( - PrivKeyTypeEd25519 = byte(0x01) - PrivKeyTypeSecp256k1 = byte(0x02) - PrivKeyNameEd25519 = "ed25519" - PrivKeyNameSecp256k1 = "secp256k1" + TypeEd25519 = byte(0x01) + TypeSecp256k1 = byte(0x02) + NameEd25519 = "ed25519" + NameSecp256k1 = "secp256k1" ) var privKeyMapper data.Mapper @@ -32,8 +32,8 @@ var privKeyMapper data.Mapper // register both private key types with go-data (and thus go-wire) func init() { privKeyMapper = data.NewMapper(PrivKeyS{}). - RegisterInterface(PrivKeyEd25519{}, PrivKeyNameEd25519, PrivKeyTypeEd25519). - RegisterInterface(PrivKeySecp256k1{}, PrivKeyNameSecp256k1, PrivKeyTypeSecp256k1) + RegisterInterface(PrivKeyEd25519{}, NameEd25519, TypeEd25519). + RegisterInterface(PrivKeySecp256k1{}, NameSecp256k1, TypeSecp256k1) } // PrivKeyS add json serialization to PrivKey diff --git a/pub_key.go b/pub_key.go index 77ce74a97..9067a0363 100644 --- a/pub_key.go +++ b/pub_key.go @@ -21,21 +21,13 @@ type PubKey interface { Equals(PubKey) bool } -// Types of PubKey implementations -const ( - PubKeyTypeEd25519 = byte(0x01) - PubKeyTypeSecp256k1 = byte(0x02) - PubKeyNameEd25519 = "ed25519" - PubKeyNameSecp256k1 = "secp256k1" -) - var pubKeyMapper data.Mapper // register both public key types with go-data (and thus go-wire) func init() { pubKeyMapper = data.NewMapper(PubKeyS{}). - RegisterInterface(PubKeyEd25519{}, PubKeyNameEd25519, PubKeyTypeEd25519). - RegisterInterface(PubKeySecp256k1{}, PubKeyNameSecp256k1, PubKeyTypeSecp256k1) + RegisterInterface(PubKeyEd25519{}, NameEd25519, TypeEd25519). + RegisterInterface(PubKeySecp256k1{}, NameSecp256k1, TypeSecp256k1) } // PubKeyS add json serialization to PubKey @@ -76,7 +68,7 @@ func (pubKey PubKeyEd25519) Address() []byte { PanicCrisis(*err) } // append type byte - encodedPubkey := append([]byte{PubKeyTypeEd25519}, w.Bytes()...) + encodedPubkey := append([]byte{TypeEd25519}, w.Bytes()...) hasher := ripemd160.New() hasher.Write(encodedPubkey) // does not error return hasher.Sum(nil) @@ -153,7 +145,7 @@ func (pubKey PubKeySecp256k1) Address() []byte { PanicCrisis(*err) } // append type byte - encodedPubkey := append([]byte{PubKeyTypeSecp256k1}, w.Bytes()...) + encodedPubkey := append([]byte{TypeSecp256k1}, w.Bytes()...) hasher := ripemd160.New() hasher.Write(encodedPubkey) // does not error return hasher.Sum(nil) diff --git a/signature.go b/signature.go index 076358879..b5fc36bf3 100644 --- a/signature.go +++ b/signature.go @@ -17,21 +17,13 @@ type Signature interface { Equals(Signature) bool } -// Types of Signature implementations -const ( - SignatureTypeEd25519 = byte(0x01) - SignatureTypeSecp256k1 = byte(0x02) - SignatureNameEd25519 = "ed25519" - SignatureNameSecp256k1 = "secp256k1" -) - var sigMapper data.Mapper // register both public key types with go-data (and thus go-wire) func init() { sigMapper = data.NewMapper(SignatureS{}). - RegisterInterface(SignatureEd25519{}, SignatureNameEd25519, SignatureTypeEd25519). - RegisterInterface(SignatureSecp256k1{}, SignatureNameSecp256k1, SignatureTypeSecp256k1) + RegisterInterface(SignatureEd25519{}, NameEd25519, TypeEd25519). + RegisterInterface(SignatureSecp256k1{}, NameSecp256k1, TypeSecp256k1) } // SignatureS add json serialization to Signature diff --git a/signature_test.go b/signature_test.go index e0e30b780..f6c8c37be 100644 --- a/signature_test.go +++ b/signature_test.go @@ -56,14 +56,14 @@ func TestSignatureEncodings(t *testing.T) { { privKey: PrivKeyS{GenPrivKeyEd25519()}, sigSize: ed25519.SignatureSize, - sigType: SignatureTypeEd25519, - sigName: SignatureNameEd25519, + sigType: TypeEd25519, + sigName: NameEd25519, }, { privKey: PrivKeyS{GenPrivKeySecp256k1()}, sigSize: 0, // unknown - sigType: SignatureTypeSecp256k1, - sigName: SignatureNameSecp256k1, + sigType: TypeSecp256k1, + sigName: NameSecp256k1, }, }