Repository navigation
PKIOverheid G4 migration #4355
Description
First analysis:
New G4 PKIoverheid Private certificates:
- Can still be used as a client certificate
- Are still valid for just as long as the current certificates
- Require support for RSA-PSS as cryptographic algorithm, in line with NCSC (mainly concerns network infrastructure, such as proxies)
- Require the inclusion of G4 Certificate Authorities in the trust store (action required from Nuts node administrators at software vendors), otherwise a requesting party may be unable to establish a
connection with a data source holder. - It is not yet clear to me from when the G4 certificates will be available
We need to find out what it means for the UZI server-certificate-backed credentials.
TODO:
- Check CPS statement: what attributes will it contain, how does the CPS differ from the old one
- Update java-didx509-toolkit if needed (not needed, verified; test in uzi-did-x509-issuer-java#5)
- Update nuts-node if needed (no production change; tests in test: cover did:x509 with PKIoverheid G4-style certificate chains #4595)
- Write migration path for community
did:x509 ca-fingerprints for G4 UZI server certificates
Pin the issuing (TSP) CA, not the shared G4 Root Priv G-TLS: KPN, DigiCert and Digidentity issue under the same root. The ca-fingerprint is the base64url-encoded, unpadded SHA-256 over the DER-encoded CA certificate.
| Production | Test (acceptatie) | |
|---|---|---|
| Issuing CA | CN=UZI Server - G4 PKIo Priv G-TLS SYS - 2025, organizationIdentifier=NTRNL-50000535, O=CIBG, C=NL |
CN=ACCEPTATIE UZI Server - G4 Priv G-TLS SYS - 2025, organizationIdentifier=NTRNL-50000535, O=CIBG, C=NL |
| Chain | Staat der Nederlanden - G4 Root Priv G-TLS - 2024 → Staat der Nederlanden - G4 Intm Priv G-TLS SYS - 2024 → issuing CA |
ACCEPTATIE Zorg CSP - G4 Root Priv G-TLS - 2024 → ACCEPTATIE Zorg CSP - G4 Intm Priv G-TLS SYS - 2024 → issuing CA |
| Valid | 2025-07-17 to 2039-05-18 | 2026-04-12 to 2039-05-18 |
| Certificate | http://cert.pkioverheid.nl/UZIServerG4PKIoPrivGTLSSYS2025.cer | http://www.uzi-register-test.nl/cacerts/acceptatie_uzi_server-g4_priv_g-tls_sys-2025.cer |
| SHA-256 (hex) | b034cbfffcafe784edaef49fefad354edbc7823d8d6522d3da6f8e91ff28aa42 |
b2f2b3371852d3b57574a91e91639957477a028effaaf8ea5de816077d988d91 |
| SHA-1 (hex) | 758b611fafbc4d178a88cb4048677ad1456cfb3c |
9da8fcc902210f0934382dd6d351d7f0f20c8775 |
| did:x509 prefix | did:x509:0:sha256:sDTL__yv54TtrvSf7601TtvHgj2NZSLT2m-Okf8oqkI |
did:x509:0:sha256:svKzNxhS07V1dKkekWOZV0d6Ao7_qvjqXegWB32YjZE |
| Policy / discovery pattern | ^did:x509:0:sha256:sDTL__yv54TtrvSf7601TtvHgj2NZSLT2m-Okf8oqkI::.*$ |
^did:x509:0:sha256:svKzNxhS07V1dKkekWOZV0d6Ao7_qvjqXegWB32YjZE::.*$ |
UZI Server - G4 PKIo Priv G-TLS SYS - 2024 (vzLz0CQ4GMpgjboDI2aaEDA9mrKoEGiv_jc1ANaUaHo) was revoked on 2025-10-29 and must not be used.
Verify yourself:
curl -sO http://cert.pkioverheid.nl/UZIServerG4PKIoPrivGTLSSYS2025.cer
openssl dgst -sha256 -binary UZIServerG4PKIoPrivGTLSSYS2025.cer | base64 | tr '+/' '-_' | tr -d '='
# sDTL__yv54TtrvSf7601TtvHgj2NZSLT2m-Okf8oqkI
Sources: production CA list https://cert.pkioverheid.nl/ and https://www.uziregister.nl/softwareleveranciers/ca-certificaten-g4 (publishes the root thumbprints, which match); test CA list https://acceptatie.zorgcsp.nl/ca-certificaten.
Migration path for use cases
Every discovery definition and access policy that pins the G1 UZI-register Private Server CA G1 must accept the G4 UZI Server - G4 PKIo Priv G-TLS SYS - 2025 CA next to it until 12-11-2028. Pattern to use (production; the test hierarchy uses the test fingerprints from the table above):
^did:x509:0:sha256:(vdhg746H4rLH67NN1unhdxo6PF3shQunCA4-KQTb2Jc|sDTL__yv54TtrvSf7601TtvHgj2NZSLT2m-Okf8oqkI)[\w\-.:%]*$
Order, per use case:
- Update the definition and policy files in the use-case repository (add G4 next to G1, never replace).
- The discovery server operator deploys the updated definition and restarts.
- Every participant deploys the updated discovery definition and access policy and restarts (both are read at startup). A node running the old files does not see, and does not issue tokens to, participants that use a G4 credential.
- Only then may participants switch to a G4 certificate: issue a new X509Credential with the toolkit, load it in the wallet, re-register on the discovery service. Their did:x509 changes.
- Add the G4 chain to the truststores:
tls.truststorefile(when the gRPC network is active) and the reverse proxy's client-certificate trust for the gRPC and FHIR endpoints. Truststores and instructions: https://nuts.nl/certs (Publish PKIoverheid truststores (G1 + G4) on nuts.nl/certs #4603).
Tracking per use case:
- G4 migration: 360 graden cliëntbeeld (nl-zorginzage) #4598 360 graden cliëntbeeld (nl-zorginzage)
- G4 migration: Huisartsinzage (Zorginzage Huisarts-VVT) #4599 Huisartsinzage (Zorginzage Huisarts-VVT), PR toepassing-zorginzage-ha-vvt#52
- G4 migration: LSPxNuts #4601 LSPxNuts
- G4 migration: Proactieve Zorgplanning (ACP/PZP) #4602 Proactieve Zorgplanning (ACP/PZP)
- Publish PKIoverheid truststores (G1 + G4) on nuts.nl/certs #4603 Publish the truststores on nuts.nl/certs
- Test the G4 migration path end-to-end with CIBG test certificates (spec v1 and v2) #4604 Test the migration path end-to-end with CIBG test certificates
Nuts spec v1 use cases (truststore only)
These use cases run on the gRPC network (did:nuts) and use no X509Credential, so their definitions do not change. Their participants only add the G4 chain to their truststores (step 5 above): tls.truststorefile and the reverse proxy's client-certificate trust. This must be done network-wide before 12-11-2026, when CIBG starts issuing G4 certificates; otherwise a node with a G4 certificate cannot connect to a node that does not trust the G4 chain.
- ANW: participants informed
- eOverdracht: participants informed
- KIK-V: participants informed
Metadata
Metadata
Assignees
Labels
Type
Fields
Priority
Activity
reinkrul commentedon Sep 25, 2026
PKIoverheid G4: concrete changes for UZI server certificates
Source: CIBG "CA model, Pasmodel, Certificaat- en CRL-profielen Zorg CSP G4" v1.1 (table 29) vs. G1 profile v10.5.2 (table 25).
What changes (G1 → G4)
CN=UZI Server - G4 PKIo Priv G-TLS SYS - 2024, O=CIBG, C=NL, under intermediateStaat der Nederlanden - G4 Intm Priv G-TLS SYS - 2024and rootStaat der Nederlanden - G4 Root Priv G-TLS - 2024. Chain depth stays 4. The G1 issuer'sorganizationIdentifier=NTRNL-50000535is no longer in the issuer DN.2.16.528.1.1003.1.2.44.15.35.11(PKIo G4 Priv TLS Gen Sys Organization Validated Server) plus ETSI NCP0.4.0.2042.1.1. CPS URI:https://www.zorgcsp.nl/certification-practice-statement-cps.http://www.csp.uzi-register.nl/cdp/uzi_server-g4_pkio_priv_g-tls_sys-2024.crl. CA issuers AIA:http://cert.pkioverheid.nl/UZIServerG4PKIoPrivGTLSSYS2024.cer. OCSP unchanged:http://ocsp.uzi-register.nl.What does not change
2.16.528.1.1003.1.3.5.5.5-1-<UZI-nr>-S-<URA>-00.000-<AGB>, and the permanentIdentifier otherName (1.3.6.1.5.5.7.8.3) carrying the URA with assigner2.16.528.1.1007.3.3.What this means for Nuts
san:otherNameandsubject:Opolicies, the URA regex, and the go-didx509-toolkit parsing need no change.pki/validator.goverifies CRLs viaCheckSignatureFrom, but nuts-node has no test coverage for it: all test chains are SHA256-RSA 2048. Add a PSS/SHA-512/4096 test chain to the did:x509 resolver and CRL tests, and run the e2e once against a CIBG G4 test certificate.reinkrul commentedon Sep 25, 2026
Supplementary findings to the change list above, in response to a claim "under G4 issuers can but whatever attribute they want in the certificate, making the X509Credential ecosystem unsafe".
What CIBG is allowed to put in a UZI server certificate
PKIoverheid Programme of Requirements v5.0 §7.1.4.2 is a closed list: "Certificates SHALL NOT contain any Subject Distinguished Name fields other than those described" and the same for subjectAltName. So a TSP cannot invent attributes; it can only choose the value layout inside an approved otherName.
NTRNL-<KvK>or OIN/HRN)<Assigner-OID>-<Subject-string>, or PermanentIdentifierCIBG's profile diverges from the generic G4 rules on two points (keeps L/ST, omits organizationIdentifier). The CIBG profile document is what gets issued; noted here only in case a later profile revision aligns it with the PoR.
Issuer
CIBG remains the TSP, operating
UZI Server - G4 PKIo Priv G-TLS SYS - 2024under the sharedG4 Root Priv G-TLS. KPN, DigiCert and Digidentity issue ordinary private server certificates under the same root, so the did:x509 anchor must be the CIBG TSP CA, not the root. No sign that server certificate issuance moves to a commercial TSP.Toolkit / nuts-node gaps (not caused by G4, but relevant)
san:permanentIdentifier.value/san:permanentIdentifier.assignerpolicies (URA + assigner2.16.528.1.1007.3.3), but nuts-node rejects those keys invdr/didx509/validation.go(unknown policy key). The URA is the only stable identifier across renewals (the UZI number in the otherName is regenerated per issuance), so supporting this would let a policy pin the URA directly.subject:organizationIdentifier(2.5.4.97) policy. Not needed for CIBG certificates, but it is the mandatory organisation identifier for every other G4 legal-entity certificate.Sources
reinkrul commentedon Sep 29, 2026
Toolkit and node checks against the G4 profile (details in #4589):
:mainimage issues a PS256 X509Credential from a chain that follows the CIBG G4 server profile (RSA 4096, RSASSA-PSS/SHA-512, UZI otherName + permanentIdentifier SANs); DID anchored on the issuing CA with the expectedsan:otherNameandsubject:O,Lpolicies.crypto/x509.Operational note for trust policies: there are already two UZI server TSP CAs under G4, and the did:x509 fingerprint must be pinned per TSP CA (not the shared G-TLS root):
UZI Server - G4 PKIo Priv G-TLS SYS - 2025:did:x509:0:sha256:sDTL__yv54TtrvSf7601TtvHgj2NZSLT2m-Okf8oqkIrevoked on 29 October 2025, do not pin it. Only the 2025 CA is currently valid.UZI Server - G4 PKIo Priv G-TLS SYS - 2024:did:x509:0:sha256:vzLz0CQ4GMpgjboDI2aaEDA9mrKoEGiv_jc1ANaUaHoStill open: repeat issuance and the e2e flow with a real CIBG G4 test server certificate (request in progress, #4589).
reinkrul commentedon Sep 30, 2026
Recorded the did:x509 ca-fingerprints for G4 UZI server certificates in the issue body (production and test environment), with a one-line verification command.
UZI Server - G4 PKIo Priv G-TLS SYS - 2025:did:x509:0:sha256:sDTL__yv54TtrvSf7601TtvHgj2NZSLT2m-Okf8oqkIACCEPTATIE UZI Server - G4 Priv G-TLS SYS - 2025:did:x509:0:sha256:svKzNxhS07V1dKkekWOZV0d6Ao7_qvjqXegWB32YjZEDouble-checked: each hash computed by three independent implementations (Go
crypto/sha256, OpenSSL, Pythonhashlib) on files freshly downloaded from cert.pkioverheid.nl and uzi-register-test.nl; both CA certificates verify against their root, and the production root's SHA-1/SHA-256 thumbprints match those published by CIBG; encoding is the same as go-didx509-toolkit uses to build the DID.Accept X509Credentials issued under PKIoverheid G4 UZI server certifi…
[-]Find out what PKIOverheid G4 means for Nuts[/-][+]PKIOverheid G4 migration[/+]reinkrul commentedon Oct 7, 2026
X509Credential issuance with the real CIBG G4 test server certificate (not only the synthetic chain), both toolkits:
:main): OK, see Test issuance and usage of X509Credential backed by a G4 certificate #4589. Issuerdid:x509:0:sha256:svKzNxhS07V1dKkekWOZV0d6Ao7_qvjqXegWB32YjZE::san:otherName:2.16.528.1.1007.99.2110-1-900034846-S-90000380-00.000-11223344::subject:L:...:O:..., PS256, 4-cert x5c. Credential then passed the nuts-node e2e flow.Observation, independent of G4: the two toolkits produce a different DID for the same certificate. Go includes
subject:Landsubject:Oby default, Java includes all of C, ST, L, O, CN (and OU when present), e.g....::subject:ST:Zuid%2DHolland:C:NL:CN:node%2Enuts%2Dservices%2Enl:L:...:O:.... The issuer patterns in the definitions ([\w\-.:%]*$after the fingerprint) accept both, so this is harmless today, but an organisation that switches toolkit gets a new did:x509.reinkrul commentedon Oct 7, 2026
Also ran the nuts-node e2e flow (
oauth-flow/didx509, image built from #4595) with the X509Credential issued by uzi-did-x509-issuer-java from the real CIBG G4 test certificate instead of the Go toolkit: credential accepted in the wallet, discovery registration found, access token issued and introspected withorganization_ura90000380, name and city from the certificate. Same result as with the Go toolkit (#4589). The Java DID carries the extrasubject:C,subject:STandsubject:CNpolicies, which the node validated against the certificate without issue.Both toolkits are therefore verified against the real G4 test certificate, both for issuance and for use in the node. Done once; not kept as a permanent test.