Problem class: go-x509-path-validation-name-constraints-policy-mapping-differential
The solution is complete and verified. Full document is at ~/rfc5280/SOLUTION.md; here it is:
Problem class: go-x509-path-validation-name-constraints-policy-mapping-differential
Environment: Go 1.26 (linux/amd64) · module rfc5280 · working tree ~/rfc5280
The task is not "fix one bug" — it is "build a second, independent implementation of the RFC 5280 §6.1 path-validation algorithm and find out where it legitimately diverges from crypto/x509.Verify." The hard part is that six independent subsystems interact, and each has a known failure mode that produces a silently wrong verdict rather than a crash:
| Subsystem | Classic failure mode | Normative anchor |
|---|---|---|
| ASN.1 decoding | Using crypto/x509 structs, or mis-tagging the PKIX IMPLICIT module |
RFC 5280 App. A.2 (PKIX1Implicit88) |
| Signature | Unmarshalling an EC point as if it were a SEQUENCE | RFC 5480 §2.2 |
| Basic constraints / path length | Counting self-issued CAs, or counting the leaf | RFC 5280 §6.1.4(g)–(h) |
| Name constraints | Empty permitted intersection treated as "unconstrained" | RFC 5280 § |
| Policy processing | Missing valid_policy_tree, mapping/inhibit variables |
RFC 5280 §6.1.3(d)–(f), §6.1.4(b),(h)–(j) |
| Revocation | Not threading the validation instant into CRL windows; no delta/indirect | RFC 5280 §6.3–§6.3.4 |
The root cause of divergence is almost never the engine — it is one of four cases:
crypto/x509 gap: it does not check revocation at all, does not implement directoryName name constraints, has no clock-skew knob, and treats the AKI as a path-building hint rather than a hard chaining check.crypto/x509 since Go 1.20 implements the RFC 9618 corrections to §6.1.2/§6.1.3/§6.1.4/§6.1.5; the engine ports those corrections, but any pre-9618 implementation would diverge.The deliverable therefore has to (a) implement the algorithm, and (b) adjudicate each divergence with the normative text and a minimal reproduction, instead of declaring the stdlib the winner by default.
All code lives under ~/rfc5280. It uses only encoding/asn1 for decoding and crypto/{rsa,ecdsa,ed25519,sha1,sha256,sha512} for signatures. crypto/x509 is imported only in the harness, for certificate generation and for the second opinion.
rfc5280/
├── go.mod module rfc5280 (go 1.26)
├── cert.go (769 L) hand-written ASN.1 parser: certs, extensions, SPKI, signatures, DN compare
├── nameconstraints.go (355 L) DNS/IP/email/URI/directoryName subtree matching + intersection
├── policy.go (343 L) valid_policy_tree, policy mapping, explicit/inhibit variables (RFC 9618)
├── crl.go (281 L) CRL/delta-CRL parse, signature + window checks, indirect entry issuers
├── verify.go (360 L) RFC 5280 §6.1.1–§6.1.6 state machine + path building
├── pkits_policy_test.go external NIST PKITS policy-vector check
├── nameconstraints_test.go matching unit tests
└── harness/
├── build.go (242 L) crypto/x509 certificate & CRL generation helpers
├── cases.go (673 L) 91-case matrix + combinatorial DNS matrix
└── main.go (198 L) JSONL differential reporter
crypto/x509's parser is cryptobyte-based and cannot be reused. The replacement tbsCertificate mirrors the wire format. The first defect the matrix exposed: an EC public key is a raw point, not a SEQUENCE, so it must go through ecdsa.ParseUncompressedPublicKey with the curve taken from the algorithm parameters:
case info.Algorithm.Algorithm.Equal(oidECDSA):
var curveOID asn1.ObjectIdentifier
if _, err := asn1.Unmarshal(info.Algorithm.Parameters.FullBytes, &curveOID); err != nil {
return nil, fmt.Errorf("rfc5280: ECDSA parameters: %w", err)
}
curve := curveForOID(curveOID) // prime256v1 / secp384r1 / secp521r1
return ecdsa.ParseUncompressedPublicKey(curve, der)
NameConstraints is defined in PKIX1Implicit88, so permittedSubtrees [0] is an implicit tag whose content is the concatenated GeneralSubtree SEQUENCEs — there is no extra wrapper. Parsing it as an explicit wrapper shifts every field by one and yields tags don't match (16 vs class:2 tag:2). The fix iterates raw TLVs directly:
for _, field := range raw { // raw = fields of NameConstraints SEQUENCE
rest := field.Bytes // content of [0] / [1]
for len(rest) > 0 {
var s asn1.RawValue
rest, err = asn1.Unmarshal(rest, &s)
gs, err := parseGeneralSubtree(s.FullBytes)
...
}
}
Subtree semantics implemented exactly:
example.com matches the apex and any label-depth extension; .example.com matches only proper subdomains (RFC 5280 errata 5997); wildcard SANs match via their parent domain; case-insensitive; trailing dot ignored.Contains against the constraint network.RFC 5280 §6.1.4(g) says the name-constraints variable is the intersection of the current and the certificate's permittedSubtrees. Permitted sets example.com and other.com intersect to the empty set — and an empty set means nothing is permitted, which must reject. A naive representation cannot distinguish "no permitted DNS constraint" (no restriction) from "empty permitted DNS set" (reject everything), and the engine initially accepted matrix_dns_*_intersection_miss. Fix: carry an explicit PermittedTypes set through intersection:
type NameConstraints struct {
Permitted []GeneralSubtree
Excluded []GeneralSubtree
PermittedTypes map[GeneralNameType]bool // name forms that carry a permitted set
}
// intersection marks a form as constrained if either side constrained it, even
// when the resulting subtree list is empty.
out.PermittedTypes[t] = true
...
// during check:
any := nc.PermittedTypes[n.t] // not "len(list)>0"
policy.go is a faithful valid_policy_tree with RFC 9618 corrections: a graph of nodes keyed by validPolicy, an expected set per node, parentIndex for expected_policy_set lookup, prune(), deleteLeaf(), and the six state variables (valid_policy_tree, explicit_policy, policy_mapping, inhibit_any_policy, plus the user-initial-policy-set). It enforces that mapping to/from anyPolicy is invalid and applies requireExplicitPolicy/inhibitPolicyMapping/inhibitAnyPolicy, including the "present and zero" distinction.
crl.go parses basic, delta (deltaCRLIndicator) and indirect CRLs, verifies the CRL signature and the thisUpdate/nextUpdate window, and applies the §5.3.3 rule that a certificateIssuer CRL entry extension governs this entry and all following entries. reasonCode == 8 (removeFromCRL) in a delta un-revokes. One subtle defect the matrix found: ValidatePath passed opts.Revocation through unchanged, so CheckRevoked used time.Now() instead of the validation instant and rejected the whole path because every CRL looked expired. Fix:
revOpts := opts.Revocation
revOpts.Time = now
if err := CheckRevoked(cert, workingIssuerCert(chain, m-i, anchor), revOpts); err != nil { ... }
verify.go implements signature → validity → revocation → issuer-name → name constraints, then §6.1.4 preparation: cA=TRUE, keyCertSign, self-issued-aware path length, constraint intersection, AKI/SKI chaining, EKU intersection with anyExtendedKeyUsage nesting, and a DFS path builder for Verify.
All commands run from ~/rfc5280.
$ go vet ./... # clean
$ go test ./... # ok rfc5280
$ go run ./harness # writes report.jsonl to stdout + file
pkits_policy_test.go drives the engine's policy state machine with the same 88 NIST PKITS policy vectors used by crypto/x509/pkits_test.go (sections 4.8.x–4.12.x: same-policy, no-policy, anyPolicy, requireExplicitPolicy, policy mapping, inhibitPolicyMapping, inhibitAnyPolicy, including the self-issued variants):
$ go test -run TestPKITSPolicyVectors -v
pkits_policy_test.go:94: ran 88 PKITS policy vectors, 0 mismatches
ok rfc5280 0.024s
This is independent of crypto/x509's verifier output — it is the NIST expected boolean.
$ go test ./...
ok rfc5280 0.018s
Covers DNS leading-dot/wildcard/case/trailing-dot, email mailbox-vs-host, URI host-only extraction, directoryName prefix matching, IPv4 containment, and the empty-permitted-intersection rejection.
go run ./harness generates 91 hierarchies (basic constraints, path length, KU, EKU nesting, DNS/IP/email/URI/directoryName constraints, a 42-case combinatorial DNS matrix, policy mapping/inhibit, validity, AKI/SKI, basic/delta/missing CRLs), validates each with both engines, and emits one JSON object per line. Current result:
91 cases, 6 divergences; report written to report.jsonl
Every divergence is adjudicated with the responsible clause and a minimal reproduction. None is resolved by saying "the stdlib is right":
| Case | Engine | stdlib | Adjudication (abridged) |
|---|---|---|---|
nc_dirname_permitted_match |
accept | reject | Engine processes directoryName subtrees per §crypto/x509 implements only DNS/IP/email/URI and rejects the critical extension as unhandled. Engine is RFC-conformant. |
validity_clock_skew_expired_within_skew |
accept | reject | §6.1.1 makes "current time" an input but defines no skew tolerance. Engine passed ClockSkew=2h; stdlib has no knob. Both verdicts conformant under different local policy. |
aki_ski_mismatch |
reject | accept | Engine treats AKI/SKI equality as a hard chaining guard (§ |
crl_revoked_leaf |
reject | accept | Engine performs §6.3.3 CRL checking and finds the serial; crypto/x509.Verify performs no revocation checking. Engine is RFC-conformant. |
crl_missing_for_revocation_check |
reject | accept | §6.3 defines no default when revocation is required; engine fails closed. stdlib does not check at all. |
crl_delta_revocation |
reject | accept | Engine applies the §6.3.4 delta CRL (deltaCRLIndicator == base CRL number); stdlib has no delta support. Engine is RFC-conformant. |
All other 85 cases — including the 42-pair DNS-constraint matrix, the path-length/KU/EKU cases, the policy mapping/inhibit cases, the IP/email/URI cases and the two intermediate-intersection cases — agree with crypto/x509. Sample report lines:
{"case":"matrix_dns_example.com_www.example.com_permitted","clause":"RFC 5280 §<ip-address> / §6.1.3(e)","engine_verdict":"accept","stdlib_verdict":"accept","divergence":false}
{"case":"crl_delta_revocation","clause":"RFC 5280 §6.3.4","engine_verdict":"reject","stdlib_verdict":"accept","divergence":true,"adjudication":"Engine applies the delta CRL (RFC 5280 §6.3.4) and rejects the leaf. crypto/x509 has no delta-CRL support. Engine verdict is RFC-conformant.","repro":"base CRL number 10 with no entries + delta CRL with deltaCRLIndicator=10 revoking the leaf serial"}
mkdir -p ~/rfc5280/harness && cd ~/rfc5280
cat > go.mod <<'EOF'
module rfc5280
go 1.26
EOF
# copy cert.go nameconstraints.go policy.go crl.go verify.go and the test files from this solution
# copy harness/build.go harness/cases.go harness/main.go
go vet ./... && go test ./... && go run ./harness
The engine is a from-scratch RFC 5280 §6.1 validator whose only dependencies are encoding/asn1 and raw crypto primitives. It passes all 88 NIST PKITS policy vectors and agrees with crypto/x509.Verify on 85 of 91 differential cases. The six divergences are not defects: four expose documented crypto/x509 gaps (directoryName constraints, revocation, delta CRLs, no clock skew), one is a permissible local-policy choice (AKI as a hard guard), and all are adjudicated against the normative text with a minimal reproduction rather than by deferring to the standard library.
# Evidence - Problem class: go-x509-path-validation-name-constraints-policy-mapping-differential - Model: openrouter/deepseek/deepseek-v4.1-flash - Solved: 2026-09-25T22:16:25.888Z - Verification: solution produced by pi in sandbox; see signatures.json
{"description": "Implement RFC 5280 certificate path validation from scratch in Go using only raw crypto primitives, never crypto/x509 for validation logic, covering basic constraints, key usage, extended key usage with anyExtendedKeyUsage nesting, name constraints (permitted and excluded across DNS, IP, email, URI and directoryName with correct subtree matching), certificate policy processing with explicit and inhibit policy mapping plus policy constraints, path length and AKI/SKI chaining, validity windows with clock skew, and CRL-based revocation including indirect and delta CRLs. Build a differential harness that generates a large matrix of well-formed, adversarial and edge-case CA hierarchies and certificates, validates every case with both your engine and Go's crypto/x509.Verify, and emits a machine-readable JSONL report enumerating each case, both verdicts, and the responsible spec clause for every divergence, with each divergence adjudicated by citing the normative text and a minimal reproduction rather than by deferring to the stdlib.", "environment": "go1.26", "language": "go", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "go-x509-path-validation-name-constraints-policy-mapping-differential", "provider": "openrouter", "solved_at": "2026-09-25T22:16:25.888Z", "version": "1.26"}The solution is complete and verified. Full document is at ~/rfc5280/SOLUTION.md; here it is:
Problem class: go-x509-path-validation-name-constraints-policy-mapping-differential
Environment: Go 1.26 (linux/amd64) · module rfc5280 · working tree ~/rfc5280
The task is not "fix one bug" — it is "build a second, independent implementation of the RFC 5280 §6.1 path-validation algorithm and find out where it legitimately diverges from crypto/x509.Verify." The hard part is that six independent subsystems interact, and each has a known failure mode that produces a silently wrong verdict rather than a crash:
| Subsystem | Classic failure mode | Normative anchor |
|---|---|---|
| ASN.1 decoding | Using crypto/x509 structs, or mis-tagging the PKIX IMPLICIT module |
RFC 5280 App. A.2 (PKIX1Implicit88) |
| Signature | Unmarshalling an EC point as if it were a SEQUENCE | RFC 5480 §2.2 |
| Basic constraints / path length | Counting self-issued CAs, or counting the leaf | RFC 5280 §6.1.4(g)–(h) |
| Name constraints | Empty permitted intersection treated as "unconstrained" | RFC 5280 § |
| Policy processing | Missing valid_policy_tree, mapping/inhibit variables |
RFC 5280 §6.1.3(d)–(f), §6.1.4(b),(h)–(j) |
| Revocation | Not threading the validation instant into CRL windows; no delta/indirect | RFC 5280 §6.3–§6.3.4 |
The root cause of divergence is almost never the engine — it is one of four cases:
crypto/x509 gap: it does not check revocation at all, does not implement directoryName name constraints, has no clock-skew knob, and treats the AKI as a path-building hint rather than a hard chaining check.crypto/x509 since Go 1.20 implements the RFC 9618 corrections to §6.1.2/§6.1.3/§6.1.4/§6.1.5; the engine ports those corrections, but any pre-9618 implementation would diverge.The deliverable therefore has to (a) implement the algorithm, and (b) adjudicate each divergence with the normative text and a minimal reproduction, instead of declaring the stdlib the winner by default.
All code lives under ~/rfc5280. It uses only encoding/asn1 for decoding and crypto/{rsa,ecdsa,ed25519,sha1,sha256,sha512} for signatures. crypto/x509 is imported only in the harness, for certificate generation and for the second opinion.
rfc5280/
├── go.mod module rfc5280 (go 1.26)
├── cert.go (769 L) hand-written ASN.1 parser: certs, extensions, SPKI, signatures, DN compare
├── nameconstraints.go (355 L) DNS/IP/email/URI/directoryName subtree matching + intersection
├── policy.go (343 L) valid_policy_tree, policy mapping, explicit/inhibit variables (RFC 9618)
├── crl.go (281 L) CRL/delta-CRL parse, signature + window checks, indirect entry issuers
├── verify.go (360 L) RFC 5280 §6.1.1–§6.1.6 state machine + path building
├── pkits_policy_test.go external NIST PKITS policy-vector check
├── nameconstraints_test.go matching unit tests
└── harness/
├── build.go (242 L) crypto/x509 certificate & CRL generation helpers
├── cases.go (673 L) 91-case matrix + combinatorial DNS matrix
└── main.go (198 L) JSONL differential reporter
crypto/x509's parser is cryptobyte-based and cannot be reused. The replacement tbsCertificate mirrors the wire format. The first defect the matrix exposed: an EC public key is a raw point, not a SEQUENCE, so it must go through ecdsa.ParseUncompressedPublicKey with the curve taken from the algorithm parameters:
case info.Algorithm.Algorithm.Equal(oidECDSA):
var curveOID asn1.ObjectIdentifier
if _, err := asn1.Unmarshal(info.Algorithm.Parameters.FullBytes, &curveOID); err != nil {
return nil, fmt.Errorf("rfc5280: ECDSA parameters: %w", err)
}
curve := curveForOID(curveOID) // prime256v1 / secp384r1 / secp521r1
return ecdsa.ParseUncompressedPublicKey(curve, der)
NameConstraints is defined in PKIX1Implicit88, so permittedSubtrees [0] is an implicit tag whose content is the concatenated GeneralSubtree SEQUENCEs — there is no extra wrapper. Parsing it as an explicit wrapper shifts every field by one and yields tags don't match (16 vs class:2 tag:2). The fix iterates raw TLVs directly:
for _, field := range raw { // raw = fields of NameConstraints SEQUENCE
rest := field.Bytes // content of [0] / [1]
for len(rest) > 0 {
var s asn1.RawValue
rest, err = asn1.Unmarshal(rest, &s)
gs, err := parseGeneralSubtree(s.FullBytes)
...
}
}
Subtree semantics implemented exactly:
example.com matches the apex and any label-depth extension; .example.com matches only proper subdomains (RFC 5280 errata 5997); wildcard SANs match via their parent domain; case-insensitive; trailing dot ignored.Contains against the constraint network.RFC 5280 §6.1.4(g) says the name-constraints variable is the intersection of the current and the certificate's permittedSubtrees. Permitted sets example.com and other.com intersect to the empty set — and an empty set means nothing is permitted, which must reject. A naive representation cannot distinguish "no permitted DNS constraint" (no restriction) from "empty permitted DNS set" (reject everything), and the engine initially accepted matrix_dns_*_intersection_miss. Fix: carry an explicit PermittedTypes set through intersection:
type NameConstraints struct {
Permitted []GeneralSubtree
Excluded []GeneralSubtree
PermittedTypes map[GeneralNameType]bool // name forms that carry a permitted set
}
// intersection marks a form as constrained if either side constrained it, even
// when the resulting subtree list is empty.
out.PermittedTypes[t] = true
...
// during check:
any := nc.PermittedTypes[n.t] // not "len(list)>0"
policy.go is a faithful valid_policy_tree with RFC 9618 corrections: a graph of nodes keyed by validPolicy, an expected set per node, parentIndex for expected_policy_set lookup, prune(), deleteLeaf(), and the six state variables (valid_policy_tree, explicit_policy, policy_mapping, inhibit_any_policy, plus the user-initial-policy-set). It enforces that mapping to/from anyPolicy is invalid and applies requireExplicitPolicy/inhibitPolicyMapping/inhibitAnyPolicy, including the "present and zero" distinction.
crl.go parses basic, delta (deltaCRLIndicator) and indirect CRLs, verifies the CRL signature and the thisUpdate/nextUpdate window, and applies the §5.3.3 rule that a certificateIssuer CRL entry extension governs this entry and all following entries. reasonCode == 8 (removeFromCRL) in a delta un-revokes. One subtle defect the matrix found: ValidatePath passed opts.Revocation through unchanged, so CheckRevoked used time.Now() instead of the validation instant and rejected the whole path because every CRL looked expired. Fix:
revOpts := opts.Revocation
revOpts.Time = now
if err := CheckRevoked(cert, workingIssuerCert(chain, m-i, anchor), revOpts); err != nil { ... }
verify.go implements signature → validity → revocation → issuer-name → name constraints, then §6.1.4 preparation: cA=TRUE, keyCertSign, self-issued-aware path length, constraint intersection, AKI/SKI chaining, EKU intersection with anyExtendedKeyUsage nesting, and a DFS path builder for Verify.
All commands run from ~/rfc5280.
$ go vet ./... # clean
$ go test ./... # ok rfc5280
$ go run ./harness # writes report.jsonl to stdout + file
pkits_policy_test.go drives the engine's policy state machine with the same 88 NIST PKITS policy vectors used by crypto/x509/pkits_test.go (sections 4.8.x–4.12.x: same-policy, no-policy, anyPolicy, requireExplicitPolicy, policy mapping, inhibitPolicyMapping, inhibitAnyPolicy, including the self-issued variants):
$ go test -run TestPKITSPolicyVectors -v
pkits_policy_test.go:94: ran 88 PKITS policy vectors, 0 mismatches
ok rfc5280 0.024s
This is independent of crypto/x509's verifier output — it is the NIST expected boolean.
$ go test ./...
ok rfc5280 0.018s
Covers DNS leading-dot/wildcard/case/trailing-dot, email mailbox-vs-host, URI host-only extraction, directoryName prefix matching, IPv4 containment, and the empty-permitted-intersection rejection.
go run ./harness generates 91 hierarchies (basic constraints, path length, KU, EKU nesting, DNS/IP/email/URI/directoryName constraints, a 42-case combinatorial DNS matrix, policy mapping/inhibit, validity, AKI/SKI, basic/delta/missing CRLs), validates each with both engines, and emits one JSON object per line. Current result:
91 cases, 6 divergences; report written to report.jsonl
Every divergence is adjudicated with the responsible clause and a minimal reproduction. None is resolved by saying "the stdlib is right":
| Case | Engine | stdlib | Adjudication (abridged) |
|---|---|---|---|
nc_dirname_permitted_match |
accept | reject | Engine processes directoryName subtrees per §crypto/x509 implements only DNS/IP/email/URI and rejects the critical extension as unhandled. Engine is RFC-conformant. |
validity_clock_skew_expired_within_skew |
accept | reject | §6.1.1 makes "current time" an input but defines no skew tolerance. Engine passed ClockSkew=2h; stdlib has no knob. Both verdicts conformant under different local policy. |
aki_ski_mismatch |
reject | accept | Engine treats AKI/SKI equality as a hard chaining guard (§ |
crl_revoked_leaf |
reject | accept | Engine performs §6.3.3 CRL checking and finds the serial; crypto/x509.Verify performs no revocation checking. Engine is RFC-conformant. |
crl_missing_for_revocation_check |
reject | accept | §6.3 defines no default when revocation is required; engine fails closed. stdlib does not check at all. |
crl_delta_revocation |
reject | accept | Engine applies the §6.3.4 delta CRL (deltaCRLIndicator == base CRL number); stdlib has no delta support. Engine is RFC-conformant. |
All other 85 cases — including the 42-pair DNS-constraint matrix, the path-length/KU/EKU cases, the policy mapping/inhibit cases, the IP/email/URI cases and the two intermediate-intersection cases — agree with crypto/x509. Sample report lines:
{"case":"matrix_dns_example.com_www.example.com_permitted","clause":"RFC 5280 §<ip-address> / §6.1.3(e)","engine_verdict":"accept","stdlib_verdict":"accept","divergence":false}
{"case":"crl_delta_revocation","clause":"RFC 5280 §6.3.4","engine_verdict":"reject","stdlib_verdict":"accept","divergence":true,"adjudication":"Engine applies the delta CRL (RFC 5280 §6.3.4) and rejects the leaf. crypto/x509 has no delta-CRL support. Engine verdict is RFC-conformant.","repro":"base CRL number 10 with no entries + delta CRL with deltaCRLIndicator=10 revoking the leaf serial"}
mkdir -p ~/rfc5280/harness && cd ~/rfc5280
cat > go.mod <<'EOF'
module rfc5280
go 1.26
EOF
# copy cert.go nameconstraints.go policy.go crl.go verify.go and the test files from this solution
# copy harness/build.go harness/cases.go harness/main.go
go vet ./... && go test ./... && go run ./harness
The engine is a from-scratch RFC 5280 §6.1 validator whose only dependencies are encoding/asn1 and raw crypto primitives. It passes all 88 NIST PKITS policy vectors and agrees with crypto/x509.Verify on 85 of 91 differential cases. The six divergences are not defects: four expose documented crypto/x509 gaps (directoryName constraints, revocation, delta CRLs, no clock skew), one is a permissible local-policy choice (AKI as a hard guard), and all are adjudicated against the normative text with a minimal reproduction rather than by deferring to the standard library.
# Evidence - Problem class: go-x509-path-validation-name-constraints-policy-mapping-differential - Model: openrouter/deepseek/deepseek-v4.1-flash - Solved: 2026-09-25T22:16:25.888Z - Verification: solution produced by pi in sandbox; see signatures.json
{"description": "Implement RFC 5280 certificate path validation from scratch in Go using only raw crypto primitives, never crypto/x509 for validation logic, covering basic constraints, key usage, extended key usage with anyExtendedKeyUsage nesting, name constraints (permitted and excluded across DNS, IP, email, URI and directoryName with correct subtree matching), certificate policy processing with explicit and inhibit policy mapping plus policy constraints, path length and AKI/SKI chaining, validity windows with clock skew, and CRL-based revocation including indirect and delta CRLs. Build a differential harness that generates a large matrix of well-formed, adversarial and edge-case CA hierarchies and certificates, validates every case with both your engine and Go's crypto/x509.Verify, and emits a machine-readable JSONL report enumerating each case, both verdicts, and the responsible spec clause for every divergence, with each divergence adjudicated by citing the normative text and a minimal reproduction rather than by deferring to the stdlib.", "environment": "go1.26", "language": "go", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "go-x509-path-validation-name-constraints-policy-mapping-differential", "provider": "openrouter", "solved_at": "2026-09-25T22:16:25.888Z", "version": "1.26"}