Skip to content

REF-13 Support CNG signing certificates and renew demo SP certificate - #85

Open
thomasnymand wants to merge 4 commits into
mainfrom
feature/REF-13-cng-signing-support-and-sp-cert-renewal
Open

REF-13 Support CNG signing certificates and renew demo SP certificate#85
thomasnymand wants to merge 4 commits into
mainfrom
feature/REF-13-cng-signing-support-and-sp-cert-renewal

Conversation

@thomasnymand

Copy link
Copy Markdown
Collaborator

Supersedes #84 (branch renamed to feature/REF-13-...).

REF-13 — CNG signing support + demo SP certificate renewal

Why

The SP's X509Certificate2.PrivateKey (legacy CryptoAPI accessor) throws Invalid provider type specified when the signing certificate's key is stored under CNG (the default for Import-PfxCertificate, e.g. "Microsoft Software Key Storage Provider"). This broke sign-on after renewing the demo service-provider certificate.

Framework changes (provider-agnostic signing)

  • SignatureProvider: sign/verify via the RSA base-class API (SignData/VerifyData with HashAlgorithmName + PKCS#1). New ToSha2CapableRsa handles CNG keys as-is, re-imports public keys, and reopens legacy PROV_RSA_FULL keys under PROV_RSA_AES so SHA-2 keeps working.
  • RsaSha1/256/512SignatureProvider reduced to a HashName property.
  • Replaced X509Certificate2.PrivateKeyGetRSAPrivateKey() in Saml20SignonHandler, Saml20LogoutHandler, Saml20AttributeQuery.
  • HttpRedirectBindingBuilder.signingKey now accepts any RSA.

Demo cert renewal + setup

  • certificates/serviceprovider.p12 renewed (previous cert expired 2023-12-01; new one valid to 2029).
  • WebsiteDemo Web.config/csproj: updated signing thumbprint, SP served on https://localhost, added NemLog-in inttest IdP metadata.
  • setup_prerequisites.ps1 / functions.ps1: import certs -Exportable; Set-CertificatePermission resolves the key file for both CNG and CSP keys; bind a localhost dev cert to port 20002 (reuse or self-sign + trust); removed the serviceprovider SSL pfx + binding, the unused expired-SP-cert install, and the oiosaml-net.dk host entry; deleted now-unused serviceprovider ssl.pfx and serviceprovider-expired.pfx.

Testing

  • Full solution builds (Debug).
  • All 153 NUnit tests pass, including the HTTP-Redirect sign/verify round-trip and XML signature fixtures.
  • Verified end-to-end: SP sign-on works with the renewed CNG-stored certificate.

🤖 Generated with Claude Code

Also fixes #70 (CA chain trust)

setup_prerequisites.ps1 left the SP certificate's root CA in the Intermediate CA store, so X509Chain terminated in an untrusted root and DefaultCertificateSpecification rejected it. Added Set-CertificateChainTrust (functions.ps1) to place the chain's root CA in Trusted Root and intermediates in Intermediate CA (and remove the misplaced root copy), called after importing serviceprovider.p12.

Fixes #70

thomasnymand and others added 3 commits July 6, 2026 11:55
Make the signature layer provider-agnostic so signing/decryption works with
CNG-stored private keys (RSACng), not just legacy CryptoAPI (RSACryptoServiceProvider).
The legacy X509Certificate2.PrivateKey accessor throws "Invalid provider type
specified" on a CNG key, which broke the SP when its signing certificate was
imported into the CNG "Microsoft Software Key Storage Provider".

Framework:
- SignatureProvider: sign/verify via the RSA base-class API (SignData/VerifyData
  with HashAlgorithmName + Pkcs1). ToSha2CapableRsa keeps it provider-agnostic:
  CNG keys pass through, public keys are re-imported, and legacy PROV_RSA_FULL
  keys are reopened under PROV_RSA_AES so SHA-2 keeps working.
- RsaSha1/256/512SignatureProvider reduced to a HashName property.
- Replace X509Certificate2.PrivateKey with GetRSAPrivateKey() in
  Saml20SignonHandler, Saml20LogoutHandler and Saml20AttributeQuery.
- HttpRedirectBindingBuilder.signingKey now accepts any RSA.

Demo service provider certificate renewal (previous cert expired 2023-12-01):
- certificates/serviceprovider.p12 replaced with the renewed cert (valid to 2029).
- WebsiteDemo Web.config/csproj: signing thumbprint updated; SP served on
  https://localhost; added NemLog-in inttest IdP metadata.

Setup scripts (setup_prerequisites.ps1 / functions.ps1):
- Import certificates as -Exportable.
- Set-CertificatePermission resolves the private key file for both CNG and CSP keys.
- Bind a localhost developer certificate to port 20002 (reuse an existing one, or
  create and trust a self-signed one); remove the serviceprovider SSL pfx + binding.
- Remove the unused expired SP signing cert install and the oiosaml-net.dk host entry.
- Delete now-unused serviceprovider ssl.pfx and serviceprovider-expired.pfx.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
setup_prerequisites.ps1 imported the SP certificate into My/TrustedPeople, but the
chain's root CA ended up in the Intermediate CA store rather than Trusted Root. As a
result X509Chain terminated in an untrusted root and DefaultCertificateSpecification
(chain + online revocation) rejected the certificate ("No valid certificates found")
when the demo IdP encrypted to / validated the service provider.

Add Set-CertificateChainTrust (functions.ps1): it places a PFX chain's root CA in
Trusted Root and intermediates in Intermediate CA, and removes the misplaced root copy
that Import-PfxCertificate leaves in Intermediate CA. Call it for serviceprovider.p12
after import.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ssion)

X509Certificate2Collection.Import resolves relative paths against the process working
directory, not PowerShell's Set-Location ($PSScriptRoot), so '..\certificates\serviceprovider.p12'
failed with "The system cannot find the path specified". Resolve to an absolute path via
Resolve-Path first, matching how the Import-PfxCertificate calls behave.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…t-devtest4)

Replace the test-devtest4 IdP metadata with the current NemLog-in Preproduction
(OIOSAML3 devtest4) metadata and update the WebsiteDemo project reference to match.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Demo service provider certificate appears to fail revocation check

1 participant