//go:build golden_generate // The golden_generate build tag is intentionally separate so CI never // regenerates the committed fixture. Run ONCE locally to (re)commit: // // ~/sdk/go1.26.5/bin/go test -tags golden_generate \ // -run TestGenerateGoldenFixture -v \ // ./pkg/adapters/crypto/composite/... // // Then commit the produced testdata/golden-1byte.pqenc and // testdata/golden-keys.json. Non-`-update` runs of TestGoldenFormat load // the committed artifacts and verify decrypt-equality. package composite import ( "bytes" "crypto/sha256" "encoding/base64" "encoding/binary" "encoding/json" "fmt" "os" "testing" "git.tswf.io/infra/go-synapse-backupper/pkg/domain/crypto" ) // deterministicRand implements io.Reader via a SHA-256 counter stream so the // golden fixture is byte-for-byte reproducible across machines and Go // toolchain versions. type deterministicRand struct { seq uint64 } func (d *deterministicRand) Read( p []byte, ) (int, error) { for offset := 0; offset < len(p); { var b [8]byte binary.BigEndian.PutUint64(b[:], d.seq) d.seq++ out := sha256.New() out.Write(b[:]) hashed := out.Sum(nil) n := copy(p[offset:], hashed) offset += n } return len(p), nil } // Hard-coded priv seeds so the committed golden-keys.json stays stable across // builds — these are the test-only private "keys" the committed golden file // decrypts against. var ( goldenPqSeed = [32]byte{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, } goldenClassicalSeed = [32]byte{ 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, } ) func TestGenerateGoldenFixture( t *testing.T, ) { pqPub := newFakePub(fakePqSchemeID, goldenPqSeed[:]) pqPriv := newFakePriv(fakePqSchemeID, goldenPqSeed[:]) classicalPub := newFakePub(fakeClassicalSchemeID, goldenClassicalSeed[:]) classicalPriv := newFakePriv(fakeClassicalSchemeID, goldenClassicalSeed[:]) reg := crypto.NewRegistry() if err := reg.Register(fakePqSchemeID, newFakePqKem); err != nil { t.Fatalf("register pq fake: %v", err) } if err := reg.Register(fakeClassicalSchemeID, newFakeClassicalKem); err != nil { t.Fatalf("register classical fake: %v", err) } enc := NewEncryptor(reg) rng := &deterministicRand{} var encrypted bytes.Buffer if err := enc.Encrypt( bytes.NewReader([]byte{0xAA}), makeRecipientPubs(pqPub, classicalPub), &encrypted, rng, ); err != nil { t.Fatalf("Encrypt: %v", err) } if err := os.MkdirAll("testdata", 0o755); err != nil { t.Fatalf("mkdir testdata: %v", err) } if err := os.WriteFile("testdata/golden-1byte.pqenc", encrypted.Bytes(), 0o644); err != nil { t.Fatalf("write golden file: %v", err) } keys := goldenKeyFile{ Pq: base64.StdEncoding.EncodeToString(pqPriv.Raw()), Classical: base64.StdEncoding.EncodeToString(classicalPriv.Raw()), } marshalled, err := json.MarshalIndent(keys, "", " ") if err != nil { t.Fatalf("marshal keys: %v", err) } marshalled = append(marshalled, '\n') if err := os.WriteFile("testdata/golden-keys.json", marshalled, 0o644); err != nil { t.Fatalf("write keys json: %v", err) } fmt.Printf("Golden fixture written: testdata/golden-1byte.pqenc (%d bytes), "+ "testdata/golden-keys.json (%d bytes)\n", len(encrypted.Bytes()), len(marshalled)) }