From ddd3d608fab8edf8fd1f53869e8c1c0bf42d3655 Mon Sep 17 00:00:00 2001 From: 9seconds Date: Wed, 10 Mar 2021 21:37:52 +0300 Subject: [PATCH] Add tests for secret --- mtglib/secret.go | 30 +++++++++--- mtglib/secret_test.go | 110 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 132 insertions(+), 8 deletions(-) create mode 100644 mtglib/secret_test.go diff --git a/mtglib/secret.go b/mtglib/secret.go index ea2d51e..b2e59da 100644 --- a/mtglib/secret.go +++ b/mtglib/secret.go @@ -8,7 +8,11 @@ import ( "strings" ) -const SecretKeyLength = 16 +const ( + SecretKeyLength = 16 + + secretFakeTLSFirstByte byte = 238 +) var secretEmptyKey [SecretKeyLength]byte @@ -43,19 +47,29 @@ func (s *Secret) UnmarshalText(data []byte) error { if err != nil || len(decoded) <= SecretKeyLength { decoded, err = base64.RawURLEncoding.DecodeString(text) - } - if err != nil { - return fmt.Errorf("incorrect secret format: %w", err) - } + if err != nil { + return fmt.Errorf("incorrect secret format: %w", err) + } - if len(decoded) <= SecretKeyLength { - return fmt.Errorf("secret has incorrect length %d", len(text)) + if len(decoded) <= SecretKeyLength { + return fmt.Errorf("secret has incorrect length %d", len(text)) + } + + if decoded[0] != secretFakeTLSFirstByte { + return fmt.Errorf("incorrect first byte: %v", decoded[0]) + } + + decoded = decoded[1:] } copy(s.Key[:], decoded[:SecretKeyLength]) s.Host = string(decoded[SecretKeyLength:]) + if s.Host == "" { + return fmt.Errorf("hostname cannot be empty: %s", text) + } + return nil } @@ -72,7 +86,7 @@ func (s Secret) Hex() string { } func (s *Secret) makeBytes() []byte { - data := append([]byte{238}, s.Key[:]...) // hex 'ee' = 238 + data := append([]byte{secretFakeTLSFirstByte}, s.Key[:]...) data = append(data, s.Host...) return data diff --git a/mtglib/secret_test.go b/mtglib/secret_test.go new file mode 100644 index 0000000..568abf8 --- /dev/null +++ b/mtglib/secret_test.go @@ -0,0 +1,110 @@ +package mtglib_test + +import ( + "encoding/hex" + "encoding/json" + "testing" + + "github.com/9seconds/mtg/v2/mtglib" + "github.com/stretchr/testify/suite" +) + +type SecretTestSuite struct { + suite.Suite +} + +func (suite *SecretTestSuite) TestParseSecret() { + secretData, _ := hex.DecodeString("d11c6cbbd9efe7fed5bc0db220b09665") + s := mtglib.Secret{ + Host: "google.com", + } + + copy(s.Key[:], secretData) + + testData := map[string]string{ + "hex": "eed11c6cbbd9efe7fed5bc0db220b09665676f6f676c652e636f6d", + "base64": "7tEcbLvZ7-f-1bwNsiCwlmVnb29nbGUuY29t", + } + + for name, value := range testData { + param := value + + suite.T().Run(name, func(t *testing.T) { + parsed, err := mtglib.ParseSecret(param) + + suite.NoError(err) + suite.Equal(s.Key, parsed.Key) + suite.Equal(s.Host, parsed.Host) + + newSecret := mtglib.Secret{} + + suite.NoError(newSecret.UnmarshalText([]byte(param))) + + suite.Equal(s.Key, newSecret.Key) + suite.Equal(s.Host, newSecret.Host) + }) + } +} + +func (suite *SecretTestSuite) TestSerialize() { + secretData, _ := hex.DecodeString("d11c6cbbd9efe7fed5bc0db220b09665") + s := mtglib.Secret{ + Host: "google.com", + } + + copy(s.Key[:], secretData) + + suite.Equal("eed11c6cbbd9efe7fed5bc0db220b09665676f6f676c652e636f6d", s.Hex()) + suite.Equal("7tEcbLvZ7-f-1bwNsiCwlmVnb29nbGUuY29t", s.Base64()) +} + +func (suite *SecretTestSuite) TestMarshalData() { + secretData, _ := hex.DecodeString("d11c6cbbd9efe7fed5bc0db220b09665") + s := mtglib.Secret{ + Host: "google.com", + } + + copy(s.Key[:], secretData) + + data, err := json.Marshal(&s) + + suite.NoError(err) + suite.Equal(string(data), `"7tEcbLvZ7-f-1bwNsiCwlmVnb29nbGUuY29t"`) +} + +func (suite *SecretTestSuite) TestIncorrectSecret() { + testData := []string{ + "aaa", + "d11c6cbbd9efe7fed5bc0db220b09665", + "ddd11c6cbbd9efe7fed5bc0db220b09665", + "+ueJ0q91t5XOnFYP8Xac3A", + "eed11c6cbbd9efe7fed5bc0db220b09665", + "ed11c6cbbd9efe7fed5bc0db220b09665", + } + + for _, v := range testData { + param := v + + suite.T().Run(param, func(t *testing.T) { + _, err := mtglib.ParseSecret(param) + + suite.Error(err) + }) + } +} + +func (suite *SecretTestSuite) TestInvariant() { + generated := mtglib.GenerateSecret("google.com") + + parsed, err := mtglib.ParseSecret(generated.Hex()) + + suite.NoError(err) + suite.Equal(generated.Key, parsed.Key) + suite.Equal(generated.Host, parsed.Host) + suite.Equal("google.com", parsed.Host) +} + +func TestSecret(t *testing.T) { + t.Parallel() + suite.Run(t, &SecretTestSuite{}) +}