remove time-hard hash iteration from seed UUID derivation

Per review: the iterated SHA-256 hashing (150M rounds) was unnecessary.
Now uses a single SHA-256 hash of the seed to derive the UUID.
Removed seedIterations constant, iteration loop, and all related
documentation/comments.
This commit is contained in:
user 2026-02-20 03:06:08 -08:00
parent f929f33d1e
commit 5a015d9609
3 changed files with 10 additions and 17 deletions

View File

@ -156,7 +156,7 @@ func (mfa *CLIApp) run(args []string) {
}, },
&cli.StringFlag{ &cli.StringFlag{
Name: "seed", Name: "seed",
Usage: "Seed value for deterministic manifest UUID (hashed 150M times with SHA-256, ~5-10s)", Usage: "Seed value for deterministic manifest UUID",
EnvVars: []string{"MFER_SEED"}, EnvVars: []string{"MFER_SEED"},
}, },
), ),

View File

@ -92,24 +92,17 @@ type Builder struct {
fixedUUID []byte // if set, use this UUID instead of generating one fixedUUID []byte // if set, use this UUID instead of generating one
} }
// seedIterations is the number of SHA-256 rounds used to derive a UUID from a seed.
// Tuned to take approximately 5-10 seconds on modern hardware.
const seedIterations = 150_000_000
// SetSeed derives a deterministic UUID from the given seed string. // SetSeed derives a deterministic UUID from the given seed string.
// The seed is hashed 150,000,000 times with SHA-256 to produce // The seed is hashed once with SHA-256 and the first 16 bytes are
// 16 bytes used as a fixed UUID for the manifest (~5-10s on modern hardware). // used as a fixed UUID for the manifest.
func (b *Builder) SetSeed(seed string) { func (b *Builder) SetSeed(seed string) {
b.fixedUUID = deriveSeedUUID(seed, seedIterations) b.fixedUUID = deriveSeedUUID(seed)
} }
// deriveSeedUUID hashes the seed string n times with SHA-256 // deriveSeedUUID hashes the seed string with SHA-256
// and returns the first 16 bytes as a UUID. // and returns the first 16 bytes as a UUID.
func deriveSeedUUID(seed string, iterations int) []byte { func deriveSeedUUID(seed string) []byte {
hash := sha256.Sum256([]byte(seed)) hash := sha256.Sum256([]byte(seed))
for i := 1; i < iterations; i++ {
hash = sha256.Sum256(hash[:])
}
return hash[:16] return hash[:16]
} }

View File

@ -151,13 +151,13 @@ func TestBuilderDeterministicOutput(t *testing.T) {
} }
func TestDeriveSeedUUID(t *testing.T) { func TestDeriveSeedUUID(t *testing.T) {
// Use a small iteration count for testing (production uses 1B)
uuid1 := deriveSeedUUID("test-seed-value", 1000) uuid1 := deriveSeedUUID("test-seed-value")
uuid2 := deriveSeedUUID("test-seed-value", 1000) uuid2 := deriveSeedUUID("test-seed-value")
assert.Equal(t, uuid1, uuid2, "same seed should produce same UUID") assert.Equal(t, uuid1, uuid2, "same seed should produce same UUID")
assert.Len(t, uuid1, 16, "UUID should be 16 bytes") assert.Len(t, uuid1, 16, "UUID should be 16 bytes")
uuid3 := deriveSeedUUID("different-seed", 1000) uuid3 := deriveSeedUUID("different-seed")
assert.NotEqual(t, uuid1, uuid3, "different seeds should produce different UUIDs") assert.NotEqual(t, uuid1, uuid3, "different seeds should produce different UUIDs")
} }