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.
111 lines
3.5 KiB
Go
111 lines
3.5 KiB
Go
package blobgen_test
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/rand"
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"sneak.berlin/go/vaultik/internal/blobgen"
|
|
)
|
|
|
|
// TestWriterHashIsDoubleHash verifies that Writer.Sum256() returns
|
|
// the double hash SHA256(SHA256(plaintext)) for security.
|
|
// Double hashing prevents attackers from confirming existence of known content.
|
|
func TestWriterHashIsDoubleHash(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
// Test data - random data that doesn't compress well
|
|
testData := make([]byte, 1024*1024) // 1MB
|
|
_, err := rand.Read(testData)
|
|
require.NoError(t, err)
|
|
|
|
// Test recipient (generated with age-keygen)
|
|
testRecipient := "age1cplgrwj77ta54dnmydvvmzn64ltk83ankxl5sww04mrtmu62kv3s89gmvv"
|
|
|
|
// Create a buffer to capture the encrypted output
|
|
var encryptedBuf bytes.Buffer
|
|
|
|
// Create blobgen writer
|
|
writer, err := blobgen.NewWriter(&encryptedBuf, 3, []string{testRecipient})
|
|
require.NoError(t, err)
|
|
|
|
// Write test data
|
|
n, err := writer.Write(testData)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, len(testData), n)
|
|
|
|
// Close to flush all data
|
|
err = writer.Close()
|
|
require.NoError(t, err)
|
|
|
|
// Get the hash from the writer
|
|
writerHash := hex.EncodeToString(writer.Sum256())
|
|
|
|
// Calculate the expected double hash: SHA256(SHA256(plaintext))
|
|
firstHash := sha256.Sum256(testData)
|
|
secondHash := sha256.Sum256(firstHash[:])
|
|
expectedDoubleHash := hex.EncodeToString(secondHash[:])
|
|
|
|
// Also compute single hash to verify it's different
|
|
singleHashStr := hex.EncodeToString(firstHash[:])
|
|
|
|
t.Logf("Input size: %d bytes", len(testData))
|
|
t.Logf("Single hash (SHA256(data)): %s", singleHashStr)
|
|
t.Logf("Double hash (SHA256(SHA256(data))): %s", expectedDoubleHash)
|
|
t.Logf("Writer hash: %s", writerHash)
|
|
|
|
// The writer hash should match the double hash
|
|
assert.Equal(t, expectedDoubleHash, writerHash,
|
|
"Writer.Sum256() should return SHA256(SHA256(plaintext)) for security")
|
|
|
|
// Verify it's NOT the single hash (would leak information)
|
|
assert.NotEqual(t, singleHashStr, writerHash,
|
|
"Writer hash should not be single hash (would allow content confirmation attacks)")
|
|
}
|
|
|
|
// TestWriterDeterministicHash verifies that the same input always produces
|
|
// the same hash, even with non-deterministic encryption.
|
|
func TestWriterDeterministicHash(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
// Test data
|
|
testData := []byte("Hello, World! This is test data for deterministic hashing.")
|
|
|
|
// Test recipient
|
|
testRecipient := "age1cplgrwj77ta54dnmydvvmzn64ltk83ankxl5sww04mrtmu62kv3s89gmvv"
|
|
|
|
// Create two writers and verify they produce the same hash
|
|
var buf1, buf2 bytes.Buffer
|
|
|
|
writer1, err := blobgen.NewWriter(&buf1, 3, []string{testRecipient})
|
|
require.NoError(t, err)
|
|
_, err = writer1.Write(testData)
|
|
require.NoError(t, err)
|
|
require.NoError(t, writer1.Close())
|
|
|
|
writer2, err := blobgen.NewWriter(&buf2, 3, []string{testRecipient})
|
|
require.NoError(t, err)
|
|
_, err = writer2.Write(testData)
|
|
require.NoError(t, err)
|
|
require.NoError(t, writer2.Close())
|
|
|
|
hash1 := hex.EncodeToString(writer1.Sum256())
|
|
hash2 := hex.EncodeToString(writer2.Sum256())
|
|
|
|
// Hashes should be identical (deterministic)
|
|
assert.Equal(t, hash1, hash2, "Same input should produce same hash")
|
|
|
|
// Encrypted outputs should be different (non-deterministic encryption)
|
|
assert.NotEqual(t, buf1.Bytes(), buf2.Bytes(),
|
|
"Encrypted outputs should differ due to non-deterministic encryption")
|
|
|
|
t.Logf("Hash 1: %s", hash1)
|
|
t.Logf("Hash 2: %s", hash2)
|
|
t.Logf("Encrypted size 1: %d bytes", buf1.Len())
|
|
t.Logf("Encrypted size 2: %d bytes", buf2.Len())
|
|
}
|