Fix every finding surfaced by the canonical .golangci.yml with golangci-lint v2.12.2 (refs #61), behavior-preserving throughout: - err113: dynamic errors replaced with package-level sentinels and %w wrapping; direct comparisons converted to errors.Is - goprintffuncname: printf-style helpers renamed with an f suffix (ui.Writer message methods, cli.ReportErrorf, database.Fatalf, vaultik stdoutf) and all call sites updated - revive: stuttering type names renamed (blob.Handler, blob.WithReader, blob.ChunkPosition, storage.URL, storage.Info), doc comments added, unused parameters blanked, package comments added - contextcheck/noctx: ctx threaded through blob.Packer (AddChunk/Flush/FinalizeBlob/PackChunks) and scanner call sites; context-aware exec and sql variants used - funlen/cyclop/gocognit/nestif/dupl: oversized or duplicated functions split into focused helpers across production and test code - paralleltest/tparallel/thelper/usetesting/testpackage: tests parallelized where safe (global log.Initialize kept in the serial phase), helpers marked, t.TempDir adopted, external test packages where only exported API is used - gosec: integer conversions clamped or justified, header timeouts added, remaining findings suppressed with per-site justifications - mnd/goconst/lll/wsl_v5/nlreturn/noinlineerr/errcheck and other mechanical findings fixed directly Remove the deprecated log.LogOptions alias (callers migrated to log.Options). make check is green.
76 lines
1.6 KiB
Go
76 lines
1.6 KiB
Go
package blobgen
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
"fmt"
|
|
"hash"
|
|
"io"
|
|
|
|
"filippo.io/age"
|
|
"github.com/klauspost/compress/zstd"
|
|
)
|
|
|
|
// Reader wraps decompression and decryption with SHA256 verification
|
|
type Reader struct {
|
|
reader io.Reader
|
|
decompressor *zstd.Decoder
|
|
decryptor io.Reader
|
|
hasher hash.Hash
|
|
teeReader io.Reader
|
|
bytesRead int64
|
|
}
|
|
|
|
// NewReader creates a new Reader that decrypts, decompresses, and verifies data
|
|
func NewReader(r io.Reader, identity age.Identity) (*Reader, error) {
|
|
// Create decryption reader
|
|
decReader, err := age.Decrypt(r, identity)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("creating decryption reader: %w", err)
|
|
}
|
|
|
|
// Create decompression reader
|
|
decompressor, err := zstd.NewReader(decReader)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("creating decompression reader: %w", err)
|
|
}
|
|
|
|
// Create SHA256 hasher
|
|
hasher := sha256.New()
|
|
|
|
// Create tee reader that reads from decompressor and writes to hasher
|
|
teeReader := io.TeeReader(decompressor, hasher)
|
|
|
|
return &Reader{
|
|
reader: r,
|
|
decompressor: decompressor,
|
|
decryptor: decReader,
|
|
hasher: hasher,
|
|
teeReader: teeReader,
|
|
}, nil
|
|
}
|
|
|
|
// Read implements io.Reader
|
|
func (r *Reader) Read(p []byte) (int, error) {
|
|
n, err := r.teeReader.Read(p)
|
|
r.bytesRead += int64(n)
|
|
|
|
return n, err
|
|
}
|
|
|
|
// Close closes the decompressor
|
|
func (r *Reader) Close() error {
|
|
r.decompressor.Close()
|
|
|
|
return nil
|
|
}
|
|
|
|
// Sum256 returns the SHA256 hash of all data read
|
|
func (r *Reader) Sum256() []byte {
|
|
return r.hasher.Sum(nil)
|
|
}
|
|
|
|
// BytesRead returns the number of uncompressed bytes read
|
|
func (r *Reader) BytesRead() int64 {
|
|
return r.bytesRead
|
|
}
|