mirror of
https://github.com/kopia/kopia.git
synced 2026-03-14 20:26:51 -04:00
content: additional tests form encryptedBlobMgr (#1583)
* content: additional tests form encryptedBlobMgr * content: tests for content.Crypter
This commit is contained in:
105
repo/content/blob_crypto_test.go
Normal file
105
repo/content/blob_crypto_test.go
Normal file
@@ -0,0 +1,105 @@
|
||||
package content_test
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/kopia/kopia/internal/gather"
|
||||
"github.com/kopia/kopia/repo/content"
|
||||
"github.com/kopia/kopia/repo/encryption"
|
||||
"github.com/kopia/kopia/repo/hashing"
|
||||
)
|
||||
|
||||
func TestBlobCrypto(t *testing.T) {
|
||||
f := &content.FormattingOptions{
|
||||
Hash: hashing.DefaultAlgorithm,
|
||||
Encryption: encryption.DefaultAlgorithm,
|
||||
}
|
||||
hf, err := hashing.CreateHashFunc(f)
|
||||
require.NoError(t, err)
|
||||
enc, err := encryption.CreateEncryptor(f)
|
||||
require.NoError(t, err)
|
||||
|
||||
cr := &content.Crypter{
|
||||
HashFunction: hf,
|
||||
Encryptor: enc,
|
||||
}
|
||||
|
||||
var tmp, tmp2, tmp3 gather.WriteBuffer
|
||||
defer tmp.Close()
|
||||
defer tmp2.Close()
|
||||
defer tmp3.Close()
|
||||
|
||||
id, err := cr.EncryptBLOB(gather.FromSlice([]byte{1, 2, 3}), "n", "mysessionid", &tmp)
|
||||
require.NoError(t, err)
|
||||
|
||||
id2, err := cr.EncryptBLOB(gather.FromSlice([]byte{1, 2, 4}), "n", "mysessionid", &tmp2)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NotEqual(t, id, id2)
|
||||
|
||||
require.NoError(t, cr.DecryptBLOB(tmp.Bytes(), id, &tmp3))
|
||||
require.Equal(t, []byte{1, 2, 3}, tmp3.ToByteSlice())
|
||||
require.NoError(t, cr.DecryptBLOB(tmp2.Bytes(), id2, &tmp3))
|
||||
require.Equal(t, []byte{1, 2, 4}, tmp3.ToByteSlice())
|
||||
|
||||
// decrypting using invalid ID fails
|
||||
require.Error(t, cr.DecryptBLOB(tmp.Bytes(), id2, &tmp3))
|
||||
require.Error(t, cr.DecryptBLOB(tmp2.Bytes(), id, &tmp3))
|
||||
|
||||
require.True(t, strings.HasPrefix(string(id), "n"))
|
||||
require.True(t, strings.HasSuffix(string(id), "-mysessionid"), id)
|
||||
|
||||
// negative cases
|
||||
require.Error(t, cr.DecryptBLOB(tmp.Bytes(), "invalid-blob-id", &tmp3))
|
||||
require.Error(t, cr.DecryptBLOB(tmp.Bytes(), "zzz0123456789abcdef0123456789abcde-suffix", &tmp3))
|
||||
require.Error(t, cr.DecryptBLOB(tmp.Bytes(), id2, &tmp3))
|
||||
require.Error(t, cr.DecryptBLOB(gather.FromSlice([]byte{2, 3, 4}), id, &tmp2))
|
||||
}
|
||||
|
||||
type badEncryptor struct{}
|
||||
|
||||
func (badEncryptor) Encrypt(input gather.Bytes, contentID []byte, output *gather.WriteBuffer) error {
|
||||
return errors.Errorf("some error")
|
||||
}
|
||||
|
||||
func (badEncryptor) Decrypt(input gather.Bytes, contentID []byte, output *gather.WriteBuffer) error {
|
||||
return errors.Errorf("some error")
|
||||
}
|
||||
|
||||
func (badEncryptor) Overhead() int { return 0 }
|
||||
|
||||
func TestBlobCrypto_Invalid(t *testing.T) {
|
||||
cr := &content.Crypter{
|
||||
HashFunction: func(output []byte, data gather.Bytes) []byte {
|
||||
// invalid hash
|
||||
return append(output, 9, 9, 9, 9)
|
||||
},
|
||||
Encryptor: badEncryptor{},
|
||||
}
|
||||
|
||||
var tmp, tmp2, tmp3 gather.WriteBuffer
|
||||
defer tmp.Close()
|
||||
defer tmp2.Close()
|
||||
defer tmp3.Close()
|
||||
|
||||
_, err := cr.EncryptBLOB(gather.FromSlice([]byte{1, 2, 3}), "n", "mysessionid", &tmp)
|
||||
require.Error(t, err)
|
||||
|
||||
f := &content.FormattingOptions{
|
||||
Hash: hashing.DefaultAlgorithm,
|
||||
Encryption: encryption.DefaultAlgorithm,
|
||||
}
|
||||
|
||||
// now fix HashFunction but encryption still fails.
|
||||
hf, err := hashing.CreateHashFunc(f)
|
||||
require.NoError(t, err)
|
||||
|
||||
cr.HashFunction = hf
|
||||
|
||||
_, err = cr.EncryptBLOB(gather.FromSlice([]byte{1, 2, 3}), "n", "mysessionid", &tmp)
|
||||
require.Error(t, err)
|
||||
}
|
||||
92
repo/content/encrypted_blob_mgr_test.go
Normal file
92
repo/content/encrypted_blob_mgr_test.go
Normal file
@@ -0,0 +1,92 @@
|
||||
package content
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/kopia/kopia/internal/blobtesting"
|
||||
"github.com/kopia/kopia/internal/gather"
|
||||
"github.com/kopia/kopia/internal/testlogging"
|
||||
"github.com/kopia/kopia/repo/blob"
|
||||
"github.com/kopia/kopia/repo/encryption"
|
||||
"github.com/kopia/kopia/repo/hashing"
|
||||
"github.com/kopia/kopia/repo/logging"
|
||||
)
|
||||
|
||||
type failingEncryptor struct {
|
||||
encryption.Encryptor
|
||||
err error
|
||||
}
|
||||
|
||||
func (f failingEncryptor) Encrypt(input gather.Bytes, contentID []byte, output *gather.WriteBuffer) error {
|
||||
return f.err
|
||||
}
|
||||
|
||||
func TestEncryptedBlobManager(t *testing.T) {
|
||||
data := blobtesting.DataMap{}
|
||||
st := blobtesting.NewMapStorage(data, nil, nil)
|
||||
fs := blobtesting.NewFaultyStorage(st)
|
||||
f := &FormattingOptions{
|
||||
Hash: hashing.DefaultAlgorithm,
|
||||
Encryption: encryption.DefaultAlgorithm,
|
||||
}
|
||||
hf, err := hashing.CreateHashFunc(f)
|
||||
require.NoError(t, err)
|
||||
enc, err := encryption.CreateEncryptor(f)
|
||||
require.NoError(t, err)
|
||||
|
||||
cr := &Crypter{
|
||||
HashFunction: hf,
|
||||
Encryptor: enc,
|
||||
}
|
||||
|
||||
ebm := encryptedBlobMgr{
|
||||
st: fs,
|
||||
crypter: cr,
|
||||
indexBlobCache: passthroughContentCache{fs},
|
||||
log: logging.NullLogger,
|
||||
}
|
||||
|
||||
ctx := testlogging.Context(t)
|
||||
|
||||
bm, err := ebm.encryptAndWriteBlob(ctx, gather.FromSlice([]byte{1, 2, 3}), "x", "session1")
|
||||
require.NoError(t, err)
|
||||
|
||||
stbm, err := st.GetMetadata(ctx, bm.BlobID)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, stbm, bm)
|
||||
|
||||
var tmp gather.WriteBuffer
|
||||
defer tmp.Close()
|
||||
|
||||
require.NoError(t, ebm.getEncryptedBlob(ctx, bm.BlobID, &tmp))
|
||||
|
||||
// data corruption
|
||||
data[bm.BlobID][0] ^= 1
|
||||
|
||||
require.Error(t, ebm.getEncryptedBlob(ctx, bm.BlobID, &tmp))
|
||||
|
||||
require.ErrorIs(t, ebm.getEncryptedBlob(ctx, "no-such-blob", &tmp), blob.ErrBlobNotFound)
|
||||
|
||||
someError := errors.Errorf("some error")
|
||||
|
||||
fs.AddFault(blobtesting.MethodPutBlob).ErrorInstead(someError)
|
||||
|
||||
_, err = ebm.encryptAndWriteBlob(ctx, gather.FromSlice([]byte{1, 2, 3, 4}), "x", "session1")
|
||||
require.ErrorIs(t, err, someError)
|
||||
|
||||
fs.AddFault(blobtesting.MethodGetMetadata).ErrorInstead(someError)
|
||||
|
||||
_, err = ebm.encryptAndWriteBlob(ctx, gather.FromSlice([]byte{1, 2, 3, 4}), "x", "session1")
|
||||
require.ErrorIs(t, err, someError)
|
||||
|
||||
someError2 := errors.Errorf("some error 2")
|
||||
|
||||
cr.Encryptor = failingEncryptor{nil, someError2}
|
||||
|
||||
_, err = ebm.encryptAndWriteBlob(ctx, gather.FromSlice([]byte{1, 2, 3, 4}), "x", "session1")
|
||||
require.ErrorIs(t, err, someError2)
|
||||
}
|
||||
Reference in New Issue
Block a user