From 0968285664ecc3690b41980e08b290198df0d068 Mon Sep 17 00:00:00 2001 From: Andy Wang Date: Sun, 18 Oct 2020 00:45:28 +0100 Subject: [PATCH] Improve test coverage --- internal/common/crypto_test.go | 94 ++++++++++++++++++++++++++++++++ internal/ecdh/curve25519_test.go | 15 +++++ 2 files changed, 109 insertions(+) create mode 100644 internal/common/crypto_test.go diff --git a/internal/common/crypto_test.go b/internal/common/crypto_test.go new file mode 100644 index 0000000..4f8a186 --- /dev/null +++ b/internal/common/crypto_test.go @@ -0,0 +1,94 @@ +package common + +import ( + "bytes" + "encoding/hex" + "errors" + "github.com/stretchr/testify/assert" + "io" + "math/rand" + "testing" +) + +const gcmTagSize = 16 + +func TestAESGCM(t *testing.T) { + // test vectors from https://luca-giuzzi.unibs.it/corsi/Support/papers-cryptography/gcm-spec.pdf + t.Run("correct 128", func(t *testing.T) { + key, _ := hex.DecodeString("00000000000000000000000000000000") + plaintext, _ := hex.DecodeString("") + nonce, _ := hex.DecodeString("000000000000000000000000") + ciphertext, _ := hex.DecodeString("") + tag, _ := hex.DecodeString("58e2fccefa7e3061367f1d57a4e7455a") + + encryptedWithTag, err := AESGCMEncrypt(nonce, key, plaintext) + assert.NoError(t, err) + assert.Equal(t, ciphertext, encryptedWithTag[:len(plaintext)]) + assert.Equal(t, tag, encryptedWithTag[len(plaintext):len(plaintext)+gcmTagSize]) + + decrypted, err := AESGCMDecrypt(nonce, key, encryptedWithTag) + assert.NoError(t, err) + // slight inconvenience here that assert.Equal does not consider a nil slice and an empty slice to be + // equal. decrypted should be []byte(nil) but plaintext is []byte{} + assert.True(t, bytes.Equal(plaintext, decrypted)) + }) + t.Run("bad key size", func(t *testing.T) { + key, _ := hex.DecodeString("0000000000000000000000000000") + plaintext, _ := hex.DecodeString("") + nonce, _ := hex.DecodeString("000000000000000000000000") + ciphertext, _ := hex.DecodeString("") + tag, _ := hex.DecodeString("58e2fccefa7e3061367f1d57a4e7455a") + + _, err := AESGCMEncrypt(nonce, key, plaintext) + assert.Error(t, err) + + _, err = AESGCMDecrypt(nonce, key, append(ciphertext, tag...)) + assert.Error(t, err) + }) + t.Run("bad nonce size", func(t *testing.T) { + key, _ := hex.DecodeString("00000000000000000000000000000000") + plaintext, _ := hex.DecodeString("") + nonce, _ := hex.DecodeString("00000000000000000000") + ciphertext, _ := hex.DecodeString("") + tag, _ := hex.DecodeString("58e2fccefa7e3061367f1d57a4e7455a") + + _, err := AESGCMEncrypt(nonce, key, plaintext) + assert.Error(t, err) + + _, err = AESGCMDecrypt(nonce, key, append(ciphertext, tag...)) + assert.Error(t, err) + }) + t.Run("bad tag", func(t *testing.T) { + key, _ := hex.DecodeString("00000000000000000000000000000000") + nonce, _ := hex.DecodeString("00000000000000000000") + ciphertext, _ := hex.DecodeString("") + tag, _ := hex.DecodeString("fffffccefa7e3061367f1d57a4e745ff") + + _, err := AESGCMDecrypt(nonce, key, append(ciphertext, tag...)) + assert.Error(t, err) + }) +} + +type failingReader struct { + fails int + reader io.Reader +} + +func (f *failingReader) Read(p []byte) (n int, err error) { + if f.fails > 0 { + f.fails -= 1 + return 0, errors.New("no data for you yet") + } else { + return f.reader.Read(p) + } +} + +func TestRandRead(t *testing.T) { + failer := &failingReader{ + fails: 3, + reader: rand.New(rand.NewSource(0)), + } + readBuf := make([]byte, 10) + RandRead(failer, readBuf) + assert.NotEqual(t, [10]byte{}, readBuf) +} diff --git a/internal/ecdh/curve25519_test.go b/internal/ecdh/curve25519_test.go index a0330b3..8e9a1c1 100644 --- a/internal/ecdh/curve25519_test.go +++ b/internal/ecdh/curve25519_test.go @@ -32,6 +32,7 @@ import ( "bytes" "crypto" "crypto/rand" + "io" "testing" ) @@ -39,6 +40,20 @@ func TestCurve25519(t *testing.T) { testECDH(t) } +func TestErrors(t *testing.T) { + reader, writer := io.Pipe() + _ = writer.Close() + _, _, err := GenerateKey(reader) + if err == nil { + t.Error("GenerateKey should return error") + } + + _, ok := Unmarshal([]byte{1}) + if ok { + t.Error("Unmarshal should return false") + } +} + func BenchmarkCurve25519(b *testing.B) { for i := 0; i < b.N; i++ { testECDH(b)