package crypto import ( "fmt" "strings" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" wire "github.com/tendermint/go-wire" data "github.com/tendermint/go-wire/data" ) type byter interface { Bytes() []byte } // go to wire encoding and back func checkWire(t *testing.T, in byter, reader interface{}, typ byte, size int) { // 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) // make sure we have the expected length assert.Equal(t, size, len(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])) } // make sure go-wire json can still figure this out... func checkWireJSON(t *testing.T, in interface{}, reader interface{}, typ byte) { // test to and from binary var err error js := wire.JSONBytes(in) btyp := fmt.Sprintf("[%d,", typ) assert.True(t, strings.HasPrefix(string(js), btyp), string(js), btyp) wire.ReadJSON(reader, js, &err) require.Nil(t, err, "%+v", err) } func TestKeyEncodings(t *testing.T) { cases := []struct { privKey PrivKey keyType byte keyName string // 1 (type byte) + size of byte array privSize, pubSize int }{ { privKey: GenPrivKeyEd25519().Wrap(), keyType: TypeEd25519, keyName: NameEd25519, privSize: 65, pubSize: 33, }, { privKey: GenPrivKeySecp256k1().Wrap(), keyType: TypeSecp256k1, keyName: NameSecp256k1, privSize: 33, pubSize: 34, }, } for _, tc := range cases { // check (de/en)codings of private key var priv2, priv3, priv4 PrivKey checkWire(t, tc.privKey, &priv2, tc.keyType, tc.privSize) assert.EqualValues(t, tc.privKey, priv2) checkJSON(t, tc.privKey, &priv3, tc.keyName) assert.EqualValues(t, tc.privKey, priv3) checkWireJSON(t, tc.privKey, &priv4, tc.keyType) assert.EqualValues(t, tc.privKey, priv4) // check (de/en)codings of public key pubKey := tc.privKey.PubKey() var pub2, pub3, pub4 PubKey checkWire(t, pubKey, &pub2, tc.keyType, tc.pubSize) assert.EqualValues(t, pubKey, pub2) checkJSON(t, pubKey, &pub3, tc.keyName) assert.EqualValues(t, pubKey, pub3) checkWireJSON(t, pubKey, &pub4, tc.keyType) assert.EqualValues(t, pubKey, pub4) } } 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 var a, b Signature toFromJSON(t, a, &b) assert.EqualValues(t, a, b) // make sure sigs are okay with nil var c, d PubKey toFromJSON(t, c, &d) assert.EqualValues(t, c, d) // make sure sigs are okay with nil var e, f PrivKey toFromJSON(t, e, &f) assert.EqualValues(t, e, f) } type SigMessage struct { Key PubKey Sig Signature } func (s SigMessage) Bytes() []byte { return wire.BinaryBytes(s) } func TestEmbededWireEncodings(t *testing.T) { assert := assert.New(t) cases := []struct { privKey PrivKey keyType byte keyName string size int // pub + sig size }{ { privKey: GenPrivKeyEd25519().Wrap(), keyType: TypeEd25519, keyName: NameEd25519, size: 2 + 32 + 64, }, // { // privKey: GenPrivKeySecp256k1().Wrap(), // keyType: TypeSecp256k1, // keyName: NameSecp256k1, // size: 2 + 33 + 72, // ugh, either 72 or 73 depending.... // }, } payload := randBytes(20) for i, tc := range cases { pubKey := tc.privKey.PubKey() sig := tc.privKey.Sign(payload) assert.True(pubKey.VerifyBytes(payload, sig), "%d", i) msg := SigMessage{ Key: pubKey, Sig: sig, } var msg2 SigMessage checkWire(t, msg, &msg2, tc.keyType, tc.size) } }