restic/key_test.go

352 lines
7.7 KiB
Go
Raw Normal View History

2014-12-05 20:45:49 +00:00
package restic_test
2014-09-23 20:39:12 +00:00
import (
2015-02-11 16:41:11 +00:00
"bytes"
2014-09-23 20:39:12 +00:00
"flag"
"io"
2014-09-23 20:39:12 +00:00
"io/ioutil"
"os"
"testing"
2014-12-05 20:45:49 +00:00
"github.com/restic/restic"
"github.com/restic/restic/backend"
"github.com/restic/restic/chunker"
2014-09-23 20:39:12 +00:00
)
var testPassword = "foobar"
2014-09-23 20:39:12 +00:00
var testCleanup = flag.Bool("test.cleanup", true, "clean up after running tests (remove local backend directory with all content)")
var testLargeCrypto = flag.Bool("test.largecrypto", false, "also test crypto functions with large payloads")
2014-09-23 20:39:12 +00:00
2014-12-21 16:02:49 +00:00
func setupBackend(t testing.TB) restic.Server {
2014-12-05 20:45:49 +00:00
tempdir, err := ioutil.TempDir("", "restic-test-")
2014-09-23 20:39:12 +00:00
ok(t, err)
b, err := backend.CreateLocal(tempdir)
ok(t, err)
2014-12-21 16:02:49 +00:00
return restic.NewServer(b)
2014-09-23 20:39:12 +00:00
}
2014-12-21 16:02:49 +00:00
func teardownBackend(t testing.TB, s restic.Server) {
2014-09-23 20:39:12 +00:00
if !*testCleanup {
2014-12-21 16:02:49 +00:00
l := s.Backend().(*backend.Local)
t.Logf("leaving local backend at %s\n", l.Location())
2014-09-23 20:39:12 +00:00
return
}
2014-12-21 16:02:49 +00:00
ok(t, s.Delete())
2014-09-23 20:39:12 +00:00
}
2014-12-21 16:02:49 +00:00
func setupKey(t testing.TB, s restic.Server, password string) *restic.Key {
k, err := restic.CreateKey(s, password)
2014-09-23 20:39:12 +00:00
ok(t, err)
return k
}
2014-09-23 20:39:12 +00:00
func TestRepo(t *testing.T) {
2014-12-21 16:02:49 +00:00
s := setupBackend(t)
defer teardownBackend(t, s)
_ = setupKey(t, s, testPassword)
2014-09-23 20:39:12 +00:00
}
func TestEncryptDecrypt(t *testing.T) {
2014-12-21 16:02:49 +00:00
s := setupBackend(t)
defer teardownBackend(t, s)
k := setupKey(t, s, testPassword)
tests := []int{5, 23, 2<<18 + 23, 1 << 20}
if *testLargeCrypto {
tests = append(tests, 7<<20+123)
}
for _, size := range tests {
data := make([]byte, size)
2015-02-11 16:41:11 +00:00
_, err := io.ReadFull(randomReader(42, size), data)
ok(t, err)
2014-12-05 20:45:49 +00:00
ciphertext := restic.GetChunkBuf("TestEncryptDecrypt")
n, err := k.Encrypt(ciphertext, data)
ok(t, err)
plaintext, err := k.Decrypt(ciphertext[:n])
ok(t, err)
2014-12-05 20:45:49 +00:00
restic.FreeChunkBuf("TestEncryptDecrypt", ciphertext)
equals(t, plaintext, data)
}
}
func TestSmallBuffer(t *testing.T) {
s := setupBackend(t)
defer teardownBackend(t, s)
k := setupKey(t, s, testPassword)
size := 600
data := make([]byte, size)
f, err := os.Open("/dev/urandom")
ok(t, err)
_, err = io.ReadFull(f, data)
ok(t, err)
ciphertext := make([]byte, size/2)
_, err = k.Encrypt(ciphertext, data)
// this must throw an error, since the target slice is too small
assert(t, err != nil && err == restic.ErrBufferTooSmall,
"expected restic.ErrBufferTooSmall, got %#v", err)
}
func TestLargeEncrypt(t *testing.T) {
if !*testLargeCrypto {
t.SkipNow()
}
2014-12-21 16:02:49 +00:00
s := setupBackend(t)
defer teardownBackend(t, s)
k := setupKey(t, s, testPassword)
for _, size := range []int{chunker.MaxSize, chunker.MaxSize + 1, chunker.MaxSize + 1<<20} {
data := make([]byte, size)
f, err := os.Open("/dev/urandom")
ok(t, err)
_, err = io.ReadFull(f, data)
ok(t, err)
2014-12-05 20:45:49 +00:00
ciphertext := make([]byte, size+restic.CiphertextExtension)
n, err := k.Encrypt(ciphertext, data)
ok(t, err)
plaintext, err := k.Decrypt(ciphertext[:n])
ok(t, err)
equals(t, plaintext, data)
}
}
func BenchmarkEncryptWriter(b *testing.B) {
2015-02-11 16:41:11 +00:00
size := 8 << 20 // 8MiB
rd := randomReader(23, size)
be := setupBackend(b)
defer teardownBackend(b, be)
k := setupKey(b, be, testPassword)
b.ResetTimer()
b.SetBytes(int64(size))
for i := 0; i < b.N; i++ {
rd.Seek(0, 0)
wr := k.EncryptTo(ioutil.Discard)
_, err := io.Copy(wr, rd)
2015-02-11 16:41:11 +00:00
ok(b, err)
}
}
func BenchmarkEncrypt(b *testing.B) {
size := 8 << 20 // 8MiB
data := make([]byte, size)
be := setupBackend(b)
defer teardownBackend(b, be)
k := setupKey(b, be, testPassword)
b.ResetTimer()
b.SetBytes(int64(size))
2015-02-17 16:51:46 +00:00
buf := make([]byte, len(data)+restic.CiphertextExtension)
for i := 0; i < b.N; i++ {
_, err := k.Encrypt(buf, data)
ok(b, err)
}
}
2015-02-11 17:36:31 +00:00
func BenchmarkDecryptReader(b *testing.B) {
be := setupBackend(b)
defer teardownBackend(b, be)
k := setupKey(b, be, testPassword)
size := 8 << 20 // 8MiB
buf := get_random(23, size)
ciphertext := make([]byte, len(buf)+restic.CiphertextExtension)
_, err := k.Encrypt(ciphertext, buf)
ok(b, err)
rd := bytes.NewReader(ciphertext)
b.ResetTimer()
b.SetBytes(int64(size))
for i := 0; i < b.N; i++ {
rd.Seek(0, 0)
decRd, err := k.DecryptFrom(rd)
ok(b, err)
_, err = io.Copy(ioutil.Discard, decRd)
ok(b, err)
}
}
func BenchmarkEncryptDecryptReader(b *testing.B) {
be := setupBackend(b)
defer teardownBackend(b, be)
k := setupKey(b, be, testPassword)
size := 8 << 20 // 8MiB
rd := randomReader(23, size)
b.ResetTimer()
b.SetBytes(int64(size))
Reduce memory usage of decryptReader benchmark old ns/op new ns/op delta BenchmarkChunkEncrypt 260007360 261144414 +0.44% BenchmarkChunkEncryptParallel 262839697 261201438 -0.62% BenchmarkArchiveDirectory 0.00 0.00 +0.00% BenchmarkEncryptWriter 86994839 88297245 +1.50% BenchmarkEncrypt 87414849 87406446 -0.01% BenchmarkDecryptReader 90354651 89948630 -0.45% BenchmarkEncryptDecryptReader 184533845 178374144 -3.34% BenchmarkDecrypt 88153894 88289705 +0.15% BenchmarkSaveJSON 213906 213917 +0.01% BenchmarkSaveFrom 75263853 74881361 -0.51% benchmark old MB/s new MB/s speedup BenchmarkChunkEncrypt 40.33 40.15 1.00x BenchmarkChunkEncryptParallel 39.89 40.14 1.01x BenchmarkEncryptWriter 96.43 95.00 0.99x BenchmarkEncrypt 95.96 95.97 1.00x BenchmarkDecryptReader 92.84 93.26 1.00x BenchmarkEncryptDecryptReader 45.46 47.03 1.03x BenchmarkDecrypt 95.16 95.01 1.00x BenchmarkSaveFrom 55.73 56.01 1.01x benchmark old allocs new allocs delta BenchmarkChunkEncrypt 113 113 +0.00% BenchmarkChunkEncryptParallel 104 104 +0.00% BenchmarkArchiveDirectory 0 0 +0.00% BenchmarkEncryptWriter 20 20 +0.00% BenchmarkEncrypt 14 14 +0.00% BenchmarkDecryptReader 18 18 +0.00% BenchmarkEncryptDecryptReader 55 40 -27.27% BenchmarkDecrypt 17 17 +0.00% BenchmarkSaveJSON 125 125 +0.00% BenchmarkSaveFrom 119 116 -2.52% benchmark old bytes new bytes delta BenchmarkChunkEncrypt 8515750 8515750 +0.00% BenchmarkChunkEncryptParallel 8515766 8515766 +0.00% BenchmarkArchiveDirectory 0 0 +0.00% BenchmarkEncryptWriter 28927 28927 +0.00% BenchmarkEncrypt 422313 422313 +0.00% BenchmarkDecryptReader 527827 527827 +0.00% BenchmarkEncryptDecryptReader 35814894 4100824 -88.55% BenchmarkDecrypt 8391127 8391127 +0.00% BenchmarkSaveJSON 9208 9208 +0.00% BenchmarkSaveFrom 40541 39694 -2.09%
2015-02-17 17:14:39 +00:00
buf := bytes.NewBuffer(nil)
2015-02-11 17:36:31 +00:00
for i := 0; i < b.N; i++ {
rd.Seek(0, 0)
Reduce memory usage of decryptReader benchmark old ns/op new ns/op delta BenchmarkChunkEncrypt 260007360 261144414 +0.44% BenchmarkChunkEncryptParallel 262839697 261201438 -0.62% BenchmarkArchiveDirectory 0.00 0.00 +0.00% BenchmarkEncryptWriter 86994839 88297245 +1.50% BenchmarkEncrypt 87414849 87406446 -0.01% BenchmarkDecryptReader 90354651 89948630 -0.45% BenchmarkEncryptDecryptReader 184533845 178374144 -3.34% BenchmarkDecrypt 88153894 88289705 +0.15% BenchmarkSaveJSON 213906 213917 +0.01% BenchmarkSaveFrom 75263853 74881361 -0.51% benchmark old MB/s new MB/s speedup BenchmarkChunkEncrypt 40.33 40.15 1.00x BenchmarkChunkEncryptParallel 39.89 40.14 1.01x BenchmarkEncryptWriter 96.43 95.00 0.99x BenchmarkEncrypt 95.96 95.97 1.00x BenchmarkDecryptReader 92.84 93.26 1.00x BenchmarkEncryptDecryptReader 45.46 47.03 1.03x BenchmarkDecrypt 95.16 95.01 1.00x BenchmarkSaveFrom 55.73 56.01 1.01x benchmark old allocs new allocs delta BenchmarkChunkEncrypt 113 113 +0.00% BenchmarkChunkEncryptParallel 104 104 +0.00% BenchmarkArchiveDirectory 0 0 +0.00% BenchmarkEncryptWriter 20 20 +0.00% BenchmarkEncrypt 14 14 +0.00% BenchmarkDecryptReader 18 18 +0.00% BenchmarkEncryptDecryptReader 55 40 -27.27% BenchmarkDecrypt 17 17 +0.00% BenchmarkSaveJSON 125 125 +0.00% BenchmarkSaveFrom 119 116 -2.52% benchmark old bytes new bytes delta BenchmarkChunkEncrypt 8515750 8515750 +0.00% BenchmarkChunkEncryptParallel 8515766 8515766 +0.00% BenchmarkArchiveDirectory 0 0 +0.00% BenchmarkEncryptWriter 28927 28927 +0.00% BenchmarkEncrypt 422313 422313 +0.00% BenchmarkDecryptReader 527827 527827 +0.00% BenchmarkEncryptDecryptReader 35814894 4100824 -88.55% BenchmarkDecrypt 8391127 8391127 +0.00% BenchmarkSaveJSON 9208 9208 +0.00% BenchmarkSaveFrom 40541 39694 -2.09%
2015-02-17 17:14:39 +00:00
buf.Reset()
wr := k.EncryptTo(buf)
_, err := io.Copy(wr, rd)
2015-02-11 17:36:31 +00:00
ok(b, err)
ok(b, wr.Close())
2015-02-11 17:36:31 +00:00
r, err := k.DecryptFrom(buf)
ok(b, err)
_, err = io.Copy(ioutil.Discard, r)
2015-02-11 17:36:31 +00:00
ok(b, err)
}
}
func BenchmarkDecrypt(b *testing.B) {
size := 8 << 20 // 8MiB
data := make([]byte, size)
2014-12-21 16:02:49 +00:00
s := setupBackend(b)
defer teardownBackend(b, s)
k := setupKey(b, s, testPassword)
2014-12-05 20:45:49 +00:00
ciphertext := restic.GetChunkBuf("BenchmarkDecrypt")
n, err := k.Encrypt(ciphertext, data)
ok(b, err)
b.ResetTimer()
b.SetBytes(int64(size))
for i := 0; i < b.N; i++ {
_, err := k.Decrypt(ciphertext[:n])
ok(b, err)
}
2014-12-05 20:45:49 +00:00
restic.FreeChunkBuf("BenchmarkDecrypt", ciphertext)
2014-09-23 20:39:12 +00:00
}
2015-02-11 16:41:11 +00:00
func TestEncryptStreamWriter(t *testing.T) {
2015-02-11 16:41:11 +00:00
s := setupBackend(t)
defer teardownBackend(t, s)
k := setupKey(t, s, testPassword)
tests := []int{5, 23, 2<<18 + 23, 1 << 20}
if *testLargeCrypto {
tests = append(tests, 7<<20+123)
}
for _, size := range tests {
data := make([]byte, size)
_, err := io.ReadFull(randomReader(42, size), data)
ok(t, err)
ciphertext := bytes.NewBuffer(nil)
wr := k.EncryptTo(ciphertext)
2015-02-11 16:41:11 +00:00
_, err = io.Copy(wr, bytes.NewReader(data))
2015-02-11 16:41:11 +00:00
ok(t, err)
ok(t, wr.Close())
2015-02-11 16:41:11 +00:00
l := len(data) + restic.CiphertextExtension
assert(t, len(ciphertext.Bytes()) == l,
2015-02-11 16:41:11 +00:00
"wrong ciphertext length: expected %d, got %d",
l, len(ciphertext.Bytes()))
2015-02-11 16:41:11 +00:00
// decrypt with default function
plaintext, err := k.Decrypt(ciphertext.Bytes())
2015-02-11 16:41:11 +00:00
ok(t, err)
assert(t, bytes.Equal(data, plaintext),
"wrong plaintext after decryption: expected %02x, got %02x",
data, plaintext)
}
}
2015-02-11 17:36:31 +00:00
func TestDecryptStreamReader(t *testing.T) {
s := setupBackend(t)
defer teardownBackend(t, s)
k := setupKey(t, s, testPassword)
tests := []int{5, 23, 2<<18 + 23, 1 << 20}
if *testLargeCrypto {
tests = append(tests, 7<<20+123)
}
for _, size := range tests {
data := make([]byte, size)
_, err := io.ReadFull(randomReader(42, size), data)
ok(t, err)
ciphertext := make([]byte, size+restic.CiphertextExtension)
// encrypt with default function
n, err := k.Encrypt(ciphertext, data)
ok(t, err)
assert(t, n == len(data)+restic.CiphertextExtension,
"wrong number of bytes returned after encryption: expected %d, got %d",
len(data)+restic.CiphertextExtension, n)
rd, err := k.DecryptFrom(bytes.NewReader(ciphertext))
ok(t, err)
plaintext, err := ioutil.ReadAll(rd)
ok(t, err)
assert(t, bytes.Equal(data, plaintext),
"wrong plaintext after decryption: expected %02x, got %02x",
data, plaintext)
}
}
2015-02-15 17:13:42 +00:00
func TestEncryptWriter(t *testing.T) {
s := setupBackend(t)
defer teardownBackend(t, s)
k := setupKey(t, s, testPassword)
tests := []int{5, 23, 2<<18 + 23, 1 << 20}
if *testLargeCrypto {
tests = append(tests, 7<<20+123)
}
for _, size := range tests {
data := make([]byte, size)
_, err := io.ReadFull(randomReader(42, size), data)
ok(t, err)
buf := bytes.NewBuffer(nil)
wr := k.EncryptTo(buf)
_, err = io.Copy(wr, bytes.NewReader(data))
ok(t, err)
ok(t, wr.Close())
ciphertext := buf.Bytes()
l := len(data) + restic.CiphertextExtension
assert(t, len(ciphertext) == l,
"wrong ciphertext length: expected %d, got %d",
l, len(ciphertext))
// decrypt with default function
plaintext, err := k.Decrypt(ciphertext)
ok(t, err)
assert(t, bytes.Equal(data, plaintext),
"wrong plaintext after decryption: expected %02x, got %02x",
data, plaintext)
}
}