Remove the unused crypto path and write the blob-ID hash step once (closes #151)
check / check (pull_request) Successful in 1m22s
check / check (pull_request) Successful in 1m22s
Production encryption and decryption already run through blobgen; the crypto package (Encryptor, Decryptor, UpdateRecipients, the fx Module) and Vaultik.GetEncryptor/GetDecryptor had no production caller. Delete crypto and route verify --deep through the same blobgen reader restore uses: it parses the age key once and reads both the database (still streamed to a temp file) and every blob through blobgen.NewReader. The second, blob-ID hash step is now one exported function, blobgen.DoubleSHA256, called by the three former copies. Writer.Sum256 (the double hash) becomes Writer.ContentID so it no longer shares the name Sum256 with Reader.Sum256 (the single plaintext hash). CompressData and CompressStream, unused outside tests, are deleted. Delete the unused, never-adopted secret/config newtypes in internal/types (the redacting AgeSecretKey and AWSSecretAccessKey plus AgeRecipient, S3Endpoint, BucketName, S3Prefix, AWSRegion, AWSAccessKeyID). Delete the uncalled CleanupIncompleteSnapshots (and deleteSnapshot, its only caller, now dead) and correct ARCHITECTURE.md. The only multi-recipient test moves to blobgen; the pre-#131 encrypted-bytes hash test is removed. Model: opus-4-8
This commit is contained in:
+21
-11
@@ -1,3 +1,6 @@
|
||||
// Package blobgen implements the blob data pipeline: streaming zstd
|
||||
// compression, age encryption, and SHA256 content hashing for blob
|
||||
// creation, plus the matching decrypt/decompress/verify reader.
|
||||
package blobgen
|
||||
|
||||
import (
|
||||
@@ -12,6 +15,18 @@ import (
|
||||
"github.com/klauspost/compress/zstd"
|
||||
)
|
||||
|
||||
// DoubleSHA256 returns the double SHA-256 of content whose single SHA-256
|
||||
// digest is sum: it hashes that digest once more. Stored objects are named by
|
||||
// this second hash so that a name never reveals whether known content is
|
||||
// present — an attacker who knows a plaintext, and thus its SHA-256, still
|
||||
// cannot derive the stored name without hashing the digest again. Both a blob
|
||||
// and the metadata database export are named this way.
|
||||
func DoubleSHA256(sum []byte) []byte {
|
||||
h := sha256.Sum256(sum)
|
||||
|
||||
return h[:]
|
||||
}
|
||||
|
||||
// Zstd compression level bounds accepted by NewWriter.
|
||||
const (
|
||||
minCompressionLevel = 1
|
||||
@@ -130,17 +145,12 @@ func (w *Writer) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Sum256 returns the double SHA256 hash of the uncompressed input data.
|
||||
// Double hashing (SHA256(SHA256(data))) prevents information leakage about
|
||||
// the plaintext - an attacker cannot confirm existence of known content
|
||||
// by computing its hash and checking for a matching blob filename.
|
||||
func (w *Writer) Sum256() []byte {
|
||||
// First hash: SHA256(plaintext)
|
||||
firstHash := w.hasher.Sum(nil)
|
||||
// Second hash: SHA256(firstHash) - this is the blob ID
|
||||
secondHash := sha256.Sum256(firstHash)
|
||||
|
||||
return secondHash[:]
|
||||
// ContentID returns the double SHA-256 of the uncompressed input data: the
|
||||
// name under which this content is stored. It is the second hash of the
|
||||
// running SHA-256, via DoubleSHA256; see that function for why content is
|
||||
// named this way rather than by its plain SHA-256.
|
||||
func (w *Writer) ContentID() []byte {
|
||||
return DoubleSHA256(w.hasher.Sum(nil))
|
||||
}
|
||||
|
||||
// BytesWritten returns the number of uncompressed bytes written
|
||||
|
||||
Reference in New Issue
Block a user