rfc6962: normalize precert SANs through dedupeLower

The x509 path lowercased names, trimmed trailing dots and wildcard
prefixes, dropped control bytes, and deduplicated; the precert
(TBS) path returned raw SAN strings with none of that, leaving the
ingest filter single-layered for precerts and inconsistent casing in
stored names. Route both paths through the same normalization; test
covers mixed case, trailing dot, wildcard, and duplicate collapse.
This commit is contained in:
lakshit verma 2026-08-24 00:43:33 +05:30
parent 7e9ca049e6
commit a6faae704b
No known key found for this signature in database
2 changed files with 21 additions and 1 deletions

View file

@ -57,7 +57,9 @@ func DecodeLeafEntry(e LeafEntry) (*DecodedLeaf, error) {
if err != nil {
return nil, err
}
out.Names = names
// Same normalization as the x509 path: lowercase, strip trailing
// dots and wildcard prefixes, reject control bytes, dedupe.
out.Names = dedupeLower(names)
out.SCTStamps = scts
default:
return nil, fmt.Errorf("unknown entry type %d", te.EntryType)

View file

@ -175,3 +175,21 @@ func TestControlBytesRejected(t *testing.T) {
t.Errorf("names = %q, want [ok.example.com]", leaf.Names)
}
}
func TestPrecertNamesNormalized(t *testing.T) {
cert := makeCert(t, []string{"Mixed.Case.Example.COM", "mixed.case.example.com.", "*.Wild.Example.com"})
signed := append(append(make([]byte, 32), uint24(len(cert.RawTBSCertificate))...), cert.RawTBSCertificate...)
leaf, err := DecodeLeafEntry(LeafEntry{LeafInput: buildLeaf(1, signed, 42)})
if err != nil {
t.Fatal(err)
}
want := []string{"mixed.case.example.com", "wild.example.com"}
if len(leaf.Names) != len(want) {
t.Fatalf("names = %v; want %v", leaf.Names, want)
}
for i := range want {
if leaf.Names[i] != want[i] {
t.Fatalf("names[%d] = %q; want %q", i, leaf.Names[i], want[i])
}
}
}