forked from TrueCloudLab/restic
Run tests on Seal/Open
This commit is contained in:
parent
e1b80859f2
commit
6fc133ad6a
2 changed files with 177 additions and 46 deletions
|
@ -114,10 +114,10 @@ func TestCrypto(t *testing.T) {
|
|||
}
|
||||
|
||||
nonce := NewRandomNonce()
|
||||
ciphertext := k.Seal(msg, nonce, tv.plaintext, nil)
|
||||
ciphertext := k.Seal(msg[0:], nonce, tv.plaintext, nil)
|
||||
|
||||
// decrypt message
|
||||
buf := make([]byte, len(tv.plaintext))
|
||||
buf := make([]byte, 0, len(tv.plaintext))
|
||||
buf, err := k.Open(buf, nonce, ciphertext, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
@ -130,7 +130,7 @@ func TestCrypto(t *testing.T) {
|
|||
// change mac, this must fail
|
||||
ciphertext[len(ciphertext)-8] ^= 0x23
|
||||
|
||||
if _, err = k.Open(buf, nonce, ciphertext, nil); err != ErrUnauthenticated {
|
||||
if _, err = k.Open(buf[:0], nonce, ciphertext, nil); err != ErrUnauthenticated {
|
||||
t.Fatal("wrong MAC value not detected")
|
||||
}
|
||||
// reset mac
|
||||
|
@ -138,7 +138,7 @@ func TestCrypto(t *testing.T) {
|
|||
|
||||
// tamper with nonce, this must fail
|
||||
nonce[2] ^= 0x88
|
||||
if _, err = k.Open(buf, nonce, ciphertext, nil); err != ErrUnauthenticated {
|
||||
if _, err = k.Open(buf[:0], nonce, ciphertext, nil); err != ErrUnauthenticated {
|
||||
t.Fatal("tampered nonce not detected")
|
||||
}
|
||||
// reset nonce
|
||||
|
@ -146,14 +146,14 @@ func TestCrypto(t *testing.T) {
|
|||
|
||||
// tamper with message, this must fail
|
||||
ciphertext[16+5] ^= 0x85
|
||||
if _, err = k.Open(buf, nonce, ciphertext, nil); err != ErrUnauthenticated {
|
||||
if _, err = k.Open(buf[:0], nonce, ciphertext, nil); err != ErrUnauthenticated {
|
||||
t.Fatal("tampered message not detected")
|
||||
}
|
||||
|
||||
// test decryption
|
||||
p := make([]byte, len(tv.ciphertext))
|
||||
nonce, ciphertext = tv.ciphertext[:16], tv.ciphertext[16:]
|
||||
p, err = k.Open(p, nonce, ciphertext, nil)
|
||||
p, err = k.Open(p[:0], nonce, ciphertext, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
|
@ -24,18 +24,17 @@ func TestEncryptDecrypt(t *testing.T) {
|
|||
|
||||
for _, size := range tests {
|
||||
data := rtest.Random(42, size)
|
||||
buf := make([]byte, size+crypto.Extension)
|
||||
buf := make([]byte, 0, size+crypto.Extension)
|
||||
|
||||
ciphertext, err := k.Encrypt(buf, data)
|
||||
rtest.OK(t, err)
|
||||
rtest.Assert(t, len(ciphertext) == len(data)+crypto.Extension,
|
||||
nonce := crypto.NewRandomNonce()
|
||||
ciphertext := k.Seal(buf[:0], nonce, data, nil)
|
||||
rtest.Assert(t, len(ciphertext) == len(data)+k.Overhead(),
|
||||
"ciphertext length does not match: want %d, got %d",
|
||||
len(data)+crypto.Extension, len(ciphertext))
|
||||
|
||||
plaintext := make([]byte, len(ciphertext))
|
||||
n, err := k.Decrypt(plaintext, ciphertext)
|
||||
plaintext := make([]byte, 0, len(ciphertext))
|
||||
plaintext, err := k.Open(plaintext[:0], nonce, ciphertext, nil)
|
||||
rtest.OK(t, err)
|
||||
plaintext = plaintext[:n]
|
||||
rtest.Assert(t, len(plaintext) == len(data),
|
||||
"plaintext length does not match: want %d, got %d",
|
||||
len(data), len(plaintext))
|
||||
|
@ -52,8 +51,9 @@ func TestSmallBuffer(t *testing.T) {
|
|||
_, err := io.ReadFull(rand.Reader, data)
|
||||
rtest.OK(t, err)
|
||||
|
||||
ciphertext := make([]byte, size/2)
|
||||
ciphertext, err = k.Encrypt(ciphertext, data)
|
||||
ciphertext := make([]byte, 0, size/2)
|
||||
nonce := crypto.NewRandomNonce()
|
||||
ciphertext = k.Seal(ciphertext[:0], nonce, data, nil)
|
||||
// this must extend the slice
|
||||
rtest.Assert(t, cap(ciphertext) > size/2,
|
||||
"expected extended slice, but capacity is only %d bytes",
|
||||
|
@ -61,9 +61,8 @@ func TestSmallBuffer(t *testing.T) {
|
|||
|
||||
// check for the correct plaintext
|
||||
plaintext := make([]byte, len(ciphertext))
|
||||
n, err := k.Decrypt(plaintext, ciphertext)
|
||||
plaintext, err = k.Open(plaintext[:0], nonce, ciphertext, nil)
|
||||
rtest.OK(t, err)
|
||||
plaintext = plaintext[:n]
|
||||
rtest.Assert(t, bytes.Equal(plaintext, data),
|
||||
"wrong plaintext returned")
|
||||
}
|
||||
|
@ -78,37 +77,169 @@ func TestSameBuffer(t *testing.T) {
|
|||
|
||||
ciphertext := make([]byte, 0, size+crypto.Extension)
|
||||
|
||||
ciphertext, err = k.Encrypt(ciphertext, data)
|
||||
rtest.OK(t, err)
|
||||
nonce := crypto.NewRandomNonce()
|
||||
ciphertext = k.Seal(ciphertext, nonce, data, nil)
|
||||
|
||||
// use the same buffer for decryption
|
||||
n, err := k.Decrypt(ciphertext, ciphertext)
|
||||
ciphertext, err = k.Open(ciphertext[:0], nonce, ciphertext, nil)
|
||||
rtest.OK(t, err)
|
||||
ciphertext = ciphertext[:n]
|
||||
rtest.Assert(t, bytes.Equal(ciphertext, data),
|
||||
"wrong plaintext returned")
|
||||
}
|
||||
|
||||
func TestCornerCases(t *testing.T) {
|
||||
func encrypt(t testing.TB, k *crypto.Key, data, ciphertext, nonce []byte) []byte {
|
||||
prefixlen := len(ciphertext)
|
||||
ciphertext = k.Seal(ciphertext, nonce, data, nil)
|
||||
if len(ciphertext) != len(data)+k.Overhead()+prefixlen {
|
||||
t.Fatalf("destination slice has wrong length, want %d, got %d",
|
||||
len(data)+k.Overhead(), len(ciphertext))
|
||||
}
|
||||
|
||||
return ciphertext
|
||||
}
|
||||
|
||||
func decryptNewSliceAndCompare(t testing.TB, k *crypto.Key, data, ciphertext, nonce []byte) {
|
||||
plaintext := make([]byte, 0, len(ciphertext))
|
||||
decryptAndCompare(t, k, data, ciphertext, nonce, plaintext)
|
||||
}
|
||||
|
||||
func decryptAndCompare(t testing.TB, k *crypto.Key, data, ciphertext, nonce, dst []byte) {
|
||||
prefix := make([]byte, len(dst))
|
||||
copy(prefix, dst)
|
||||
|
||||
plaintext, err := k.Open(dst, nonce, ciphertext, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to decrypt ciphertext: %v", err)
|
||||
}
|
||||
|
||||
if len(data)+len(prefix) != len(plaintext) {
|
||||
t.Fatalf("wrong plaintext returned, want %d bytes, got %d", len(data)+len(prefix), len(plaintext))
|
||||
}
|
||||
|
||||
if !bytes.Equal(plaintext[:len(prefix)], prefix) {
|
||||
t.Fatal("prefix is wrong")
|
||||
}
|
||||
|
||||
if !bytes.Equal(plaintext[len(prefix):], data) {
|
||||
t.Fatal("wrong plaintext returned")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppendSeal(t *testing.T) {
|
||||
k := crypto.NewRandomKey()
|
||||
nonce := crypto.NewRandomNonce()
|
||||
|
||||
data := make([]byte, 600)
|
||||
_, err := io.ReadFull(rand.Reader, data)
|
||||
rtest.OK(t, err)
|
||||
ciphertext := encrypt(t, k, data, nil, nonce)
|
||||
|
||||
// we need to test several different cases:
|
||||
// * destination slice is nil
|
||||
// * destination slice is empty and has enough capacity
|
||||
// * destination slice is empty and does not have enough capacity
|
||||
// * destination slice contains data and has enough capacity
|
||||
// * destination slice contains data and does not have enough capacity
|
||||
|
||||
// destination slice is nil
|
||||
t.Run("nil", func(t *testing.T) {
|
||||
var plaintext []byte
|
||||
decryptAndCompare(t, k, data, ciphertext, nonce, plaintext)
|
||||
})
|
||||
|
||||
// destination slice is empty and has enough capacity
|
||||
t.Run("empty-large", func(t *testing.T) {
|
||||
plaintext := make([]byte, 0, len(data)+100)
|
||||
decryptAndCompare(t, k, data, ciphertext, nonce, plaintext)
|
||||
})
|
||||
|
||||
// destination slice is empty and does not have enough capacity
|
||||
t.Run("empty-small", func(t *testing.T) {
|
||||
plaintext := make([]byte, 0, len(data)/2)
|
||||
decryptAndCompare(t, k, data, ciphertext, nonce, plaintext)
|
||||
})
|
||||
|
||||
// destination slice contains data and has enough capacity
|
||||
t.Run("prefix-large", func(t *testing.T) {
|
||||
plaintext := make([]byte, 0, len(data)+100)
|
||||
plaintext = append(plaintext, []byte("foobar")...)
|
||||
decryptAndCompare(t, k, data, ciphertext, nonce, plaintext)
|
||||
})
|
||||
|
||||
// destination slice contains data and does not have enough capacity
|
||||
t.Run("prefix-small", func(t *testing.T) {
|
||||
plaintext := make([]byte, 0, len(data)/2)
|
||||
plaintext = append(plaintext, []byte("foobar")...)
|
||||
decryptAndCompare(t, k, data, ciphertext, nonce, plaintext)
|
||||
})
|
||||
}
|
||||
|
||||
func TestAppendOpen(t *testing.T) {
|
||||
k := crypto.NewRandomKey()
|
||||
|
||||
// nil plaintext should encrypt to the empty string
|
||||
// nil ciphertext should allocate a new slice for the ciphertext
|
||||
c, err := k.Encrypt(nil, nil)
|
||||
data := make([]byte, 600)
|
||||
_, err := io.ReadFull(rand.Reader, data)
|
||||
rtest.OK(t, err)
|
||||
|
||||
rtest.Assert(t, len(c) == crypto.Extension,
|
||||
"wrong length returned for ciphertext, expected 0, got %d",
|
||||
len(c))
|
||||
// we need to test several different cases:
|
||||
// * destination slice is nil
|
||||
// * destination slice is empty and has enough capacity
|
||||
// * destination slice is empty and does not have enough capacity
|
||||
// * destination slice contains data and has enough capacity
|
||||
// * destination slice contains data and does not have enough capacity
|
||||
|
||||
// this should decrypt to nil
|
||||
n, err := k.Decrypt(nil, c)
|
||||
rtest.OK(t, err)
|
||||
rtest.Equals(t, 0, n)
|
||||
// destination slice is nil
|
||||
t.Run("nil", func(t *testing.T) {
|
||||
nonce := crypto.NewRandomNonce()
|
||||
var ciphertext []byte
|
||||
|
||||
// test encryption for same slice, this should return an error
|
||||
_, err = k.Encrypt(c, c)
|
||||
rtest.Equals(t, crypto.ErrInvalidCiphertext, err)
|
||||
ciphertext = encrypt(t, k, data, ciphertext, nonce)
|
||||
decryptNewSliceAndCompare(t, k, data, ciphertext, nonce)
|
||||
})
|
||||
|
||||
// destination slice is empty and has enough capacity
|
||||
t.Run("empty-large", func(t *testing.T) {
|
||||
nonce := crypto.NewRandomNonce()
|
||||
ciphertext := make([]byte, 0, len(data)+100)
|
||||
|
||||
ciphertext = encrypt(t, k, data, ciphertext, nonce)
|
||||
decryptNewSliceAndCompare(t, k, data, ciphertext, nonce)
|
||||
})
|
||||
|
||||
// destination slice is empty and does not have enough capacity
|
||||
t.Run("empty-small", func(t *testing.T) {
|
||||
nonce := crypto.NewRandomNonce()
|
||||
ciphertext := make([]byte, 0, len(data)/2)
|
||||
|
||||
ciphertext = encrypt(t, k, data, ciphertext, nonce)
|
||||
decryptNewSliceAndCompare(t, k, data, ciphertext, nonce)
|
||||
})
|
||||
|
||||
// destination slice contains data and has enough capacity
|
||||
t.Run("prefix-large", func(t *testing.T) {
|
||||
nonce := crypto.NewRandomNonce()
|
||||
ciphertext := make([]byte, 0, len(data)+100)
|
||||
ciphertext = append(ciphertext, []byte("foobar")...)
|
||||
|
||||
ciphertext = encrypt(t, k, data, ciphertext, nonce)
|
||||
if string(ciphertext[:6]) != "foobar" {
|
||||
t.Errorf("prefix is missing")
|
||||
}
|
||||
decryptNewSliceAndCompare(t, k, data, ciphertext[6:], nonce)
|
||||
})
|
||||
|
||||
// destination slice contains data and does not have enough capacity
|
||||
t.Run("prefix-small", func(t *testing.T) {
|
||||
nonce := crypto.NewRandomNonce()
|
||||
ciphertext := make([]byte, 0, len(data)/2)
|
||||
ciphertext = append(ciphertext, []byte("foobar")...)
|
||||
|
||||
ciphertext = encrypt(t, k, data, ciphertext, nonce)
|
||||
if string(ciphertext[:6]) != "foobar" {
|
||||
t.Errorf("prefix is missing")
|
||||
}
|
||||
decryptNewSliceAndCompare(t, k, data, ciphertext[6:], nonce)
|
||||
})
|
||||
}
|
||||
|
||||
func TestLargeEncrypt(t *testing.T) {
|
||||
|
@ -123,10 +254,9 @@ func TestLargeEncrypt(t *testing.T) {
|
|||
_, err := io.ReadFull(rand.Reader, data)
|
||||
rtest.OK(t, err)
|
||||
|
||||
ciphertext, err := k.Encrypt(make([]byte, size+crypto.Extension), data)
|
||||
rtest.OK(t, err)
|
||||
|
||||
plaintext, err := k.Decrypt([]byte{}, ciphertext)
|
||||
nonce := crypto.NewRandomNonce()
|
||||
ciphertext := k.Seal(make([]byte, size+k.Overhead()), nonce, data, nil)
|
||||
plaintext, err := k.Open([]byte{}, nonce, ciphertext, nil)
|
||||
rtest.OK(t, err)
|
||||
|
||||
rtest.Equals(t, plaintext, data)
|
||||
|
@ -139,13 +269,13 @@ func BenchmarkEncrypt(b *testing.B) {
|
|||
|
||||
k := crypto.NewRandomKey()
|
||||
buf := make([]byte, len(data)+crypto.Extension)
|
||||
nonce := crypto.NewRandomNonce()
|
||||
|
||||
b.ResetTimer()
|
||||
b.SetBytes(int64(size))
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, err := k.Encrypt(buf, data)
|
||||
rtest.OK(b, err)
|
||||
_ = k.Seal(buf, nonce, data, nil)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -155,17 +285,18 @@ func BenchmarkDecrypt(b *testing.B) {
|
|||
|
||||
k := crypto.NewRandomKey()
|
||||
|
||||
plaintext := make([]byte, size)
|
||||
ciphertext := make([]byte, size+crypto.Extension)
|
||||
plaintext := make([]byte, 0, size)
|
||||
ciphertext := make([]byte, 0, size+crypto.Extension)
|
||||
nonce := crypto.NewRandomNonce()
|
||||
ciphertext = k.Seal(ciphertext, nonce, data, nil)
|
||||
|
||||
ciphertext, err := k.Encrypt(ciphertext, data)
|
||||
rtest.OK(b, err)
|
||||
var err error
|
||||
|
||||
b.ResetTimer()
|
||||
b.SetBytes(int64(size))
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, err = k.Decrypt(plaintext, ciphertext)
|
||||
_, err = k.Open(plaintext, nonce, ciphertext, nil)
|
||||
rtest.OK(b, err)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue