Use Seal/Open everywhere

This commit is contained in:
Alexander Neumann
2017-10-29 11:33:57 +01:00
parent a5f0e9ab65
commit 931e6ed2ac
6 changed files with 49 additions and 59 deletions

View File

@@ -87,12 +87,12 @@ func OpenKey(ctx context.Context, s *Repository, name string, password string) (
}
// decrypt master keys
buf := make([]byte, len(k.Data))
n, err := k.user.Decrypt(buf, k.Data)
nonce, ciphertext := k.Data[:k.user.NonceSize()], k.Data[k.user.NonceSize():]
buf := make([]byte, 0, len(ciphertext))
buf, err = k.user.Open(buf, nonce, ciphertext, nil)
if err != nil {
return nil, err
}
buf = buf[:n]
// restore json
k.master = &crypto.Key{}
@@ -221,7 +221,11 @@ func AddKey(ctx context.Context, s *Repository, password string, template *crypt
return nil, errors.Wrap(err, "Marshal")
}
newkey.Data, err = newkey.user.Encrypt(nil, buf)
nonce := crypto.NewRandomNonce()
ciphertext := make([]byte, 0, len(buf)+newkey.user.Overhead()+newkey.user.NonceSize())
ciphertext = append(ciphertext, nonce...)
ciphertext = newkey.user.Seal(ciphertext, nonce, buf, nil)
newkey.Data = ciphertext
// dump as json
buf, err = json.Marshal(newkey)

View File

@@ -90,14 +90,13 @@ func Repack(ctx context.Context, repo restic.Repository, packs restic.IDSet, kee
h, tempfile.Name(), len(buf), n)
}
n, err = repo.Key().Decrypt(buf, buf)
nonce, ciphertext := buf[:repo.Key().NonceSize()], buf[repo.Key().NonceSize():]
plaintext, err := repo.Key().Open(ciphertext[:0], nonce, ciphertext, nil)
if err != nil {
return nil, err
}
buf = buf[:n]
id := restic.Hash(buf)
id := restic.Hash(plaintext)
if !id.Equal(entry.ID) {
debug.Log("read blob %v/%v from %v: wrong data returned, hash is %v",
h.Type, h.ID, tempfile.Name(), id)
@@ -105,7 +104,7 @@ func Repack(ctx context.Context, repo restic.Repository, packs restic.IDSet, kee
h, tempfile.Name(), id)
}
_, err = repo.SaveBlob(ctx, entry.Type, buf, entry.ID)
_, err = repo.SaveBlob(ctx, entry.Type, plaintext, entry.ID)
if err != nil {
return nil, err
}

View File

@@ -79,13 +79,13 @@ func (r *Repository) LoadAndDecrypt(ctx context.Context, t restic.FileType, id r
return nil, errors.Errorf("load %v: invalid data returned", h)
}
// decrypt
n, err := r.decryptTo(buf, buf)
nonce, ciphertext := buf[:r.key.NonceSize()], buf[r.key.NonceSize():]
plaintext, err := r.key.Open(ciphertext[:0], nonce, ciphertext, nil)
if err != nil {
return nil, err
}
return buf[:n], nil
return plaintext, nil
}
// sortCachedPacks moves all cached pack files to the front of blobs.
@@ -156,20 +156,22 @@ func (r *Repository) loadBlob(ctx context.Context, id restic.ID, t restic.BlobTy
}
// decrypt
n, err = r.decryptTo(plaintextBuf, plaintextBuf)
nonce, ciphertext := plaintextBuf[:r.key.NonceSize()], plaintextBuf[r.key.NonceSize():]
plaintext, err := r.key.Open(ciphertext[:0], nonce, ciphertext, nil)
if err != nil {
lastError = errors.Errorf("decrypting blob %v failed: %v", id, err)
continue
}
plaintextBuf = plaintextBuf[:n]
// check hash
if !restic.Hash(plaintextBuf).Equal(id) {
if !restic.Hash(plaintext).Equal(id) {
lastError = errors.Errorf("blob %v returned invalid hash", id)
continue
}
return len(plaintextBuf), nil
// move decrypted data to the start of the provided buffer
copy(plaintextBuf[0:], plaintext)
return len(plaintext), nil
}
if lastError != nil {
@@ -210,11 +212,12 @@ func (r *Repository) SaveAndEncrypt(ctx context.Context, t restic.BlobType, data
ciphertext := getBuf()
defer freeBuf(ciphertext)
ciphertext = ciphertext[:0]
nonce := crypto.NewRandomNonce()
ciphertext = append(ciphertext, nonce...)
// encrypt blob
ciphertext, err := r.Encrypt(ciphertext, data)
if err != nil {
return restic.ID{}, err
}
ciphertext = r.key.Seal(ciphertext, nonce, data, nil)
// find suitable packer and add blob
var pm *packerManager
@@ -266,10 +269,11 @@ func (r *Repository) SaveJSONUnpacked(ctx context.Context, t restic.FileType, it
// storage hash.
func (r *Repository) SaveUnpacked(ctx context.Context, t restic.FileType, p []byte) (id restic.ID, err error) {
ciphertext := restic.NewBlobBuffer(len(p))
ciphertext, err = r.Encrypt(ciphertext, p)
if err != nil {
return restic.ID{}, err
}
ciphertext = ciphertext[:0]
nonce := crypto.NewRandomNonce()
ciphertext = append(ciphertext, nonce...)
ciphertext = r.key.Seal(ciphertext, nonce, p, nil)
id = restic.Hash(ciphertext)
h := restic.Handle{Type: t, Name: id.String()}
@@ -522,26 +526,6 @@ func (r *Repository) init(ctx context.Context, password string, cfg restic.Confi
return err
}
// decrypt authenticates and decrypts ciphertext and stores the result in
// plaintext.
func (r *Repository) decryptTo(plaintext, ciphertext []byte) (int, error) {
if r.key == nil {
return 0, errors.New("key for repository not set")
}
return r.key.Decrypt(plaintext, ciphertext)
}
// Encrypt encrypts and authenticates the plaintext and saves the result in
// ciphertext.
func (r *Repository) Encrypt(ciphertext, plaintext []byte) ([]byte, error) {
if r.key == nil {
return nil, errors.New("key for repository not set")
}
return r.key.Encrypt(ciphertext, plaintext)
}
// Key returns the current master key.
func (r *Repository) Key() *crypto.Key {
return r.key