forked from TrueCloudLab/restic
backup: verify blobs before upload
This only covers the blobs themselves, the pack header is not verified so far. Unpacked files are also not covered by the integrity check.
This commit is contained in:
parent
16e3f79e8b
commit
c01a0c6da7
1 changed files with 26 additions and 0 deletions
|
@ -423,6 +423,11 @@ func (r *Repository) saveAndEncrypt(ctx context.Context, t restic.BlobType, data
|
|||
// encrypt blob
|
||||
ciphertext = r.key.Seal(ciphertext, nonce, data, nil)
|
||||
|
||||
if err := r.verifyCiphertext(ciphertext, uncompressedLength, id); err != nil {
|
||||
// FIXME call to action
|
||||
return 0, fmt.Errorf("detected data corruption while saving blob %v: %w", id, err)
|
||||
}
|
||||
|
||||
// find suitable packer and add blob
|
||||
var pm *packerManager
|
||||
|
||||
|
@ -438,6 +443,27 @@ func (r *Repository) saveAndEncrypt(ctx context.Context, t restic.BlobType, data
|
|||
return pm.SaveBlob(ctx, t, id, ciphertext, uncompressedLength)
|
||||
}
|
||||
|
||||
func (r *Repository) verifyCiphertext(buf []byte, uncompressedLength int, id restic.ID) error {
|
||||
nonce, ciphertext := buf[:r.key.NonceSize()], buf[r.key.NonceSize():]
|
||||
plaintext, err := r.key.Open(nil, nonce, ciphertext, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("decryption failed: %w", err)
|
||||
}
|
||||
if uncompressedLength != 0 {
|
||||
// DecodeAll will allocate a slice if it is not large enough since it
|
||||
// knows the decompressed size (because we're using EncodeAll)
|
||||
plaintext, err = r.getZstdDecoder().DecodeAll(plaintext, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("decompression failed: %w", err)
|
||||
}
|
||||
}
|
||||
if !restic.Hash(plaintext).Equal(id) {
|
||||
return errors.New("hash mismatch")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Repository) compressUnpacked(p []byte) ([]byte, error) {
|
||||
// compression is only available starting from version 2
|
||||
if r.cfg.Version < 2 {
|
||||
|
|
Loading…
Reference in a new issue