From 0781c12ede58390a77f6ea5c7245e120895a6127 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Fri, 28 Jul 2017 23:44:16 -0400 Subject: [PATCH] Message encoding for nano --- nano/sign.go | 59 +++++++++++++++++++++++++++++++++++++++++++++++ nano/sign_test.go | 51 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+) create mode 100644 nano/sign.go create mode 100644 nano/sign_test.go diff --git a/nano/sign.go b/nano/sign.go new file mode 100644 index 000000000..fbe550548 --- /dev/null +++ b/nano/sign.go @@ -0,0 +1,59 @@ +package nano + +import ( + "bytes" + "fmt" + + "github.com/pkg/errors" +) + +const ( + App = 0x80 + Init = 0x00 + Update = 0x01 + Digest = 0x02 + MaxChunk = 253 + KeyLength = 65 + SigLength = 64 +) + +var separator = []byte{0, 0xCA, 0xFE, 0} + +func generateSignRequests(payload []byte) [][]byte { + // nice one-shot + digest := []byte{App, Digest} + if len(payload) < MaxChunk { + return [][]byte{append(digest, payload...)} + } + + // large payload is multi-chunk + result := [][]byte{{App, Init}} + update := []byte{App, Update} + for len(payload) > MaxChunk { + msg := append(update, payload[:MaxChunk]...) + payload = payload[MaxChunk:] + result = append(result, msg) + } + result = append(result, append(update, payload...)) + result = append(result, digest) + return result +} + +func parseDigest(resp []byte) (key, sig []byte, err error) { + if resp[0] != App || resp[1] != Digest { + return nil, nil, errors.New("Invalid header") + } + resp = resp[2:] + if len(resp) != KeyLength+SigLength+len(separator) { + return nil, nil, errors.Errorf("Incorrect length: %d", len(resp)) + } + + key, resp = resp[:KeyLength], resp[KeyLength:] + if !bytes.Equal(separator, resp[:len(separator)]) { + return nil, nil, errors.New("Cannot find 0xCAFE") + } + fmt.Println("successs") + + sig = resp[len(separator):] + return key, sig, nil +} diff --git a/nano/sign_test.go b/nano/sign_test.go new file mode 100644 index 000000000..8029ef828 --- /dev/null +++ b/nano/sign_test.go @@ -0,0 +1,51 @@ +package nano + +import ( + "encoding/hex" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestParseDigest(t *testing.T) { + assert, require := assert.New(t), require.New(t) + + cases := []struct { + output string + key string + sig string + valid bool + }{ + { + output: "800204338EB1DD3CCDEE1F6FB586F66E640F56FFDD14537A3F0ED9EEEDF10B528FE4195FD17AC9EDAE9718A50196A1459E2434C1E53F1238F4CFDF177FAFBA8B39249B00CAFE00FFDEA42A699205B217004E7E2FFB884E174A548D644116F4B20469CBC32F60A9CB0EEB5BB6A7F266BD0F6A0A99A45B4F18F0F477AED7C854C404EF43530DAB00", + key: "04338EB1DD3CCDEE1F6FB586F66E640F56FFDD14537A3F0ED9EEEDF10B528FE4195FD17AC9EDAE9718A50196A1459E2434C1E53F1238F4CFDF177FAFBA8B39249B", + sig: "FFDEA42A699205B217004E7E2FFB884E174A548D644116F4B20469CBC32F60A9CB0EEB5BB6A7F266BD0F6A0A99A45B4F18F0F477AED7C854C404EF43530DAB00", + valid: true, + }, + { + output: "800235467890876543525437890796574535467890", + key: "", + sig: "", + valid: false, + }, + } + + for i, tc := range cases { + msg, err := hex.DecodeString(tc.output) + require.Nil(err, "%d: %+v", i, err) + + lKey, lSig, err := parseDigest(msg) + if !tc.valid { + assert.NotNil(err, "%d", i) + } else if assert.Nil(err, "%d: %+v", i, err) { + key, err := hex.DecodeString(tc.key) + require.Nil(err, "%d: %+v", i, err) + sig, err := hex.DecodeString(tc.sig) + require.Nil(err, "%d: %+v", i, err) + + assert.Equal(key, lKey, "%d", i) + assert.Equal(sig, lSig, "%d", i) + } + } +}