diff --git a/certificates/serviceprovider ssl.pfx b/certificates/serviceprovider ssl.pfx deleted file mode 100644 index 0b08722..0000000 Binary files a/certificates/serviceprovider ssl.pfx and /dev/null differ diff --git a/certificates/serviceprovider-expired.pfx b/certificates/serviceprovider-expired.pfx deleted file mode 100644 index 08282b8..0000000 Binary files a/certificates/serviceprovider-expired.pfx and /dev/null differ diff --git a/certificates/serviceprovider.p12 b/certificates/serviceprovider.p12 index 785b1a6..38e512e 100644 Binary files a/certificates/serviceprovider.p12 and b/certificates/serviceprovider.p12 differ diff --git a/setup/functions.ps1 b/setup/functions.ps1 index ccb3459..b44a62a 100644 --- a/setup/functions.ps1 +++ b/setup/functions.ps1 @@ -43,29 +43,120 @@ function Set-CertificatePermission $cert = Get-ChildItem -Path cert:\LocalMachine\My | Where-Object -FilterScript { $PSItem.ThumbPrint -eq $pfxThumbPrint; }; + if ($null -eq $cert) + { + throw "Certificate with thumbprint $pfxThumbPrint was not found in Cert:\LocalMachine\My"; + } + # Specify the user, the permissions and the permission type $permission = "$($serviceAccount)","Read,FullControl","Allow" $accessRule = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule -ArgumentList $permission; - # Location of the machine related keys - $keyPath = $env:ProgramData + "\Microsoft\Crypto\RSA\MachineKeys\"; - $keyName = $cert.PrivateKey.CspKeyContainerInfo.UniqueKeyContainerName; - $keyFullPath = $keyPath + $keyName; + # Resolve the private key file in a provider-agnostic way so this works for both modern CNG keys + # and legacy CryptoAPI (CSP) keys. Depending on how the certificate was imported, the key may be + # stored under CNG (Microsoft\Crypto\Keys) or legacy CSP (Microsoft\Crypto\RSA\MachineKeys). + # The old code used $cert.PrivateKey.CspKeyContainerInfo directly, which throws for CNG-stored keys. + # Collect every candidate location and apply the ACL to whichever file actually exists. + $candidateFiles = New-Object System.Collections.Generic.List[string]; + # CNG keys: Microsoft\Crypto\Keys, container file name = CngKey.UniqueName try { - # Get the current acl of the private key - # This is the line that fails! - $acl = Get-Acl -Path $keyFullPath; + $cngRsa = [System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($cert); + if ($cngRsa -is [System.Security.Cryptography.RSACng] -and -not [string]::IsNullOrEmpty($cngRsa.Key.UniqueName)) + { + $candidateFiles.Add($env:ProgramData + "\Microsoft\Crypto\Keys\" + $cngRsa.Key.UniqueName); + } + } + catch { } - # Add the new ace to the acl of the private key - $acl.AddAccessRule($accessRule); + # Legacy CSP keys: Microsoft\Crypto\RSA\MachineKeys, container file name = UniqueKeyContainerName + try + { + $cspRsa = $cert.PrivateKey; + if ($null -ne $cspRsa -and $null -ne $cspRsa.CspKeyContainerInfo -and -not [string]::IsNullOrEmpty($cspRsa.CspKeyContainerInfo.UniqueKeyContainerName)) + { + $candidateFiles.Add($env:ProgramData + "\Microsoft\Crypto\RSA\MachineKeys\" + $cspRsa.CspKeyContainerInfo.UniqueKeyContainerName); + } + } + catch { } - # Write back the new acl - Set-Acl -Path $keyFullPath -AclObject $acl; + $applied = $false; + foreach ($keyFullPath in ($candidateFiles | Select-Object -Unique)) + { + if (Test-Path -Path $keyFullPath) + { + $acl = Get-Acl -Path $keyFullPath; + $acl.AddAccessRule($accessRule); + Set-Acl -Path $keyFullPath -AclObject $acl; + $applied = $true; + } + } + + if (-not $applied) + { + throw "Could not locate the private key file for certificate $pfxThumbPrint (checked both the CNG and CSP key stores). The certificate's key provider metadata may be inconsistent - re-import the certificate cleanly."; + } +} + +function Set-CertificateChainTrust +{ + # Ensures the CA chain contained in a PFX is trusted for X.509 chain building: the root CA is placed + # in Trusted Root (LocalMachine\Root) and intermediate CAs in Intermediate CA (LocalMachine\CA). + # Import-PfxCertificate drops all CA certificates - including the root - into the Intermediate CA store, + # where a root is not a trust anchor, so any misplaced root copy is removed from Intermediate CA. + # Without this, DefaultCertificateSpecification (chain + online revocation) rejects the certificate + # because the chain terminates in an untrusted root (see GitHub issue #70). + param + ( + [Parameter(Position=1, Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string]$pfxPath, + + [Parameter(Position=2, Mandatory=$true)] + [ValidateNotNull()] + [System.Security.SecureString]$pfxPassword + ) + + $plainPassword = (New-Object System.Net.NetworkCredential('', $pfxPassword)).Password + + # X509Certificate2Collection.Import is a raw .NET call and resolves relative paths against the process + # working directory, not PowerShell's current location (Set-Location / $PSScriptRoot). Resolve to an + # absolute path first so a relative $pfxPath works the same way as the Import-PfxCertificate calls do. + $resolvedPfxPath = (Resolve-Path -Path $pfxPath).ProviderPath + + $chain = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2Collection + $chain.Import($resolvedPfxPath, $plainPassword, 'DefaultKeySet') + + $intermediateStore = New-Object System.Security.Cryptography.X509Certificates.X509Store('CA', 'LocalMachine') + $rootStore = New-Object System.Security.Cryptography.X509Certificates.X509Store('Root', 'LocalMachine') + $intermediateStore.Open('ReadWrite') + $rootStore.Open('ReadWrite') + try + { + foreach ($cert in $chain) + { + if ($cert.HasPrivateKey) { continue } # leaf (end-entity) is imported separately into My + + if ($cert.Subject -eq $cert.Issuer) + { + # Self-signed => root CA. Trust it, then remove any misplaced copy from Intermediate CA. + $rootStore.Add($cert); + $misplaced = $intermediateStore.Certificates.Find('FindByThumbprint', $cert.Thumbprint, $false); + foreach ($m in $misplaced) { $intermediateStore.Remove($m) } + write-host "Trusted root CA '$($cert.Subject)' ($($cert.Thumbprint)) in Trusted Root Certification Authorities" + } + else + { + # Intermediate CA + $intermediateStore.Add($cert); + write-host "Installed intermediate CA '$($cert.Subject)' ($($cert.Thumbprint)) in Intermediate Certification Authorities" + } + } } - catch + finally { - throw $_; + $intermediateStore.Close() + $rootStore.Close() } } \ No newline at end of file diff --git a/setup/setup_prerequisites.ps1 b/setup/setup_prerequisites.ps1 index 85b8a34..15ea6ee 100644 --- a/setup/setup_prerequisites.ps1 +++ b/setup/setup_prerequisites.ps1 @@ -11,38 +11,30 @@ $certpassword = ConvertTo-SecureString -String "test1234" -AsPlainText -Force $certpassword2 = ConvertTo-SecureString -String "Test1234" -AsPlainText -Force write-host "Installing demoidp ssl certificate" -$demoIdpSslcertificate = Import-PfxCertificate '..\certificates\demoidp ssl.pfx' -Password $certpassword -CertStoreLocation Cert:\LocalMachine\My -$demoIdpSslcertificate = Import-PfxCertificate '..\certificates\demoidp ssl.pfx' -Password $certpassword -CertStoreLocation Cert:\LocalMachine\TrustedPeople -write-host "Installed demo idp ssl certificate $($sslcertificate.Thumbprint) in LocalMachine\My and LocalMachine\TrustedPeople. This ensures the certificate is trusted on your machine and browser" - -write-host "Installing demoidp ssl certificate" -$serviceProviderSslcertificate = Import-PfxCertificate '..\certificates\serviceprovider ssl.pfx' -Password $certpassword -CertStoreLocation Cert:\LocalMachine\My -$serviceProviderSslcertificate = Import-PfxCertificate '..\certificates\serviceprovider ssl.pfx' -Password $certpassword -CertStoreLocation Cert:\LocalMachine\TrustedPeople -write-host "Installed demo idp ssl certificate $($sslcertificate.Thumbprint) in LocalMachine\My and LocalMachine\TrustedPeople. This ensures the certificate is trusted on your machine and browser" +$demoIdpSslcertificate = Import-PfxCertificate '..\certificates\demoidp ssl.pfx' -Password $certpassword -CertStoreLocation Cert:\LocalMachine\My -Exportable +$demoIdpSslcertificate = Import-PfxCertificate '..\certificates\demoidp ssl.pfx' -Password $certpassword -CertStoreLocation Cert:\LocalMachine\TrustedPeople -Exportable +write-host "Installed demo idp ssl certificate $($demoIdpSslcertificate.Thumbprint) in LocalMachine\My and LocalMachine\TrustedPeople. This ensures the certificate is trusted on your machine and browser" write-host "Installing demoidp's signing certificate" -$demoidpcertificate = Import-PfxCertificate '..\certificates\demoidp.pfx' -Password $certpassword -CertStoreLocation Cert:\LocalMachine\My -$demoidpcertificate = Import-PfxCertificate '..\certificates\demoidp.pfx' -Password $certpassword -CertStoreLocation Cert:\LocalMachine\TrustedPeople +$demoidpcertificate = Import-PfxCertificate '..\certificates\demoidp.pfx' -Password $certpassword -CertStoreLocation Cert:\LocalMachine\My -Exportable +$demoidpcertificate = Import-PfxCertificate '..\certificates\demoidp.pfx' -Password $certpassword -CertStoreLocation Cert:\LocalMachine\TrustedPeople -Exportable write-host "Installed demoidp's signing certificate $($demoidpcertificate.Thumbprint) in LocalMachine\My and LocalMachine\TrustedPeople. This ensures the certificate is trusted on your machine and browser" write-host "This certificate must be configured as the signing certificate for the demoidp" write-host "Installing demoidp's expired signing certificate" -$demoidpexpiredcertificate = Import-PfxCertificate '..\certificates\demoidp-expired.pfx' -Password $certpassword -CertStoreLocation Cert:\LocalMachine\My -$demoidpexpiredcertificate = Import-PfxCertificate '..\certificates\demoidp-expired.pfx' -Password $certpassword -CertStoreLocation Cert:\LocalMachine\TrustedPeople +$demoidpexpiredcertificate = Import-PfxCertificate '..\certificates\demoidp-expired.pfx' -Password $certpassword -CertStoreLocation Cert:\LocalMachine\My -Exportable +$demoidpexpiredcertificate = Import-PfxCertificate '..\certificates\demoidp-expired.pfx' -Password $certpassword -CertStoreLocation Cert:\LocalMachine\TrustedPeople -Exportable write-host "Installed demoidp's expired signing certificate $($demoidpexpiredcertificate.Thumbprint) in LocalMachine\My and LocalMachine\TrustedPeople. This ensures the certificate is trusted on your machine and browser" write-host "This certificate is automatically configured as one of the signing certificates for the demoidp" write-host "Installing serviceprovider's signing certificate" -$serviceprovidercertificate = Import-PfxCertificate '..\certificates\serviceprovider.p12' -Password $certpassword2 -CertStoreLocation Cert:\LocalMachine\My -$serviceprovidercertificate = Import-PfxCertificate '..\certificates\serviceprovider.p12' -Password $certpassword2 -CertStoreLocation Cert:\LocalMachine\TrustedPeople +$serviceprovidercertificate = Import-PfxCertificate '..\certificates\serviceprovider.p12' -Password $certpassword2 -CertStoreLocation Cert:\LocalMachine\My -Exportable +$serviceprovidercertificate = Import-PfxCertificate '..\certificates\serviceprovider.p12' -Password $certpassword2 -CertStoreLocation Cert:\LocalMachine\TrustedPeople -Exportable write-host "Installed serviceprovider's signing certificate $($serviceprovidercertificate.Thumbprint) in LocalMachine\My and LocalMachine\TrustedPeople. This ensures the certificate is trusted on your machine and browser" write-host "This certificate is used by the demo website (service provider) as its current signing certificate" -write-host "Installing serviceprovider's expired signing certificate" -$serviceproviderexpiredcertificate = Import-PfxCertificate '..\certificates\serviceprovider-expired.pfx' -Password $certpassword -CertStoreLocation Cert:\LocalMachine\My -$serviceproviderexpiredcertificate = Import-PfxCertificate '..\certificates\serviceprovider-expired.pfx' -Password $certpassword -CertStoreLocation Cert:\LocalMachine\TrustedPeople -write-host "Installed serviceprovider's expired signing certificate $($serviceproviderexpiredcertificate.Thumbprint) in LocalMachine\My and LocalMachine\TrustedPeople. This ensures the certificate is trusted on your machine and browser" -write-host "This certificate is used by the demo website (service provider) as one of its signing certificates" +write-host "Trusting the serviceprovider certificate's CA chain so X.509 chain building succeeds (see GitHub issue #70)" +Set-CertificateChainTrust '..\certificates\serviceprovider.p12' $certpassword2 #If you need to redo sslcert binding, the following statements will delete previously creates ones #"http delete sslcert ipport=0.0.0.0:20001" | netsh @@ -50,8 +42,32 @@ write-host "This certificate is used by the demo website (service provider) as o write-host "Registering demo idp ssl certificate $($demoIdpSslcertificate.Thumbprint) for SSL bindings for demo sites" "http add sslcert ipport=0.0.0.0:20001 certhash=$($demoIdpSslcertificate.Thumbprint) appid={$([Guid]::NewGuid().ToString().ToUpper())}" | netsh -write-host "Registering service provider ssl certificate $($serviceProviderSslcertificate.Thumbprint) for SSL bindings for demo sites" -"http add sslcert ipport=0.0.0.0:20002 certhash=$($serviceProviderSslcertificate.Thumbprint) appid={$([Guid]::NewGuid().ToString().ToUpper())}" | netsh +# The service provider demo runs on https://localhost:20002. Bind the machine's localhost developer +# certificate (e.g. the IIS Express Development Certificate) to that port instead of a project-specific +# SSL certificate - it matches 'localhost' (no name-mismatch warning) and is already trusted. +$localhostDevCert = Get-ChildItem Cert:\LocalMachine\My | + Where-Object { $_.FriendlyName -eq 'IIS Express Development Certificate' -or $_.Subject -eq 'CN=localhost' } | + Sort-Object NotAfter -Descending | Select-Object -First 1 +if ($null -eq $localhostDevCert) +{ + write-host "No localhost developer certificate found in Cert:\LocalMachine\My - creating a self-signed one" + $localhostDevCert = New-SelfSignedCertificate ` + -Type SSLServerAuthentication ` + -DnsName "localhost" ` + -FriendlyName "OIOSAML demo localhost developer certificate" ` + -CertStoreLocation "Cert:\LocalMachine\My" ` + -NotAfter (Get-Date).AddYears(5) ` + -KeyExportPolicy Exportable + + # A self-signed certificate is its own root, so add it to Trusted Root so browsers trust https://localhost. + $rootStore = New-Object System.Security.Cryptography.X509Certificates.X509Store("Root", "LocalMachine") + $rootStore.Open("ReadWrite") + $rootStore.Add($localhostDevCert) + $rootStore.Close() + write-host "Created and trusted self-signed localhost certificate $($localhostDevCert.Thumbprint)" +} +write-host "Registering localhost developer certificate $($localhostDevCert.Thumbprint) for the SSL binding on port 20002" +"http add sslcert ipport=0.0.0.0:20002 certhash=$($localhostDevCert.Thumbprint) appid={$([Guid]::NewGuid().ToString().ToUpper())}" | netsh write-host "If you want to re-run the sslcert bindings, you must manually delete the sslcert's (look inside this script for guidance)" @@ -62,11 +78,8 @@ write-host "Setting private key access for your identity $username on the servic Set-CertificatePermission $serviceprovidercertificate.Thumbprint $username write-host "Setting private key access for your identity $username on the demo idp signing expired certificate $($demoidpexpiredcertificate.Thumbprint) in the certificate store" Set-CertificatePermission $demoidpexpiredcertificate.Thumbprint $username -write-host "Setting private key access for your identity $username on the service provider signing expired certificate $($serviceproviderexpiredcertificate.Thumbprint) in the certificate store" -Set-CertificatePermission $serviceproviderexpiredcertificate.Thumbprint $username add-HostEntry "127.0.0.1" "oiosaml-demoidp.dk" -add-HostEntry "127.0.0.1" "oiosaml-net.dk" write-host "Setup completed!" write-host "You should now open the solution in Visual Studio, build it and run it!" diff --git a/src/dk.nita.saml20/WebsiteDemo/Web.config b/src/dk.nita.saml20/WebsiteDemo/Web.config index 7f13ac2..aafdf49 100644 --- a/src/dk.nita.saml20/WebsiteDemo/Web.config +++ b/src/dk.nita.saml20/WebsiteDemo/Web.config @@ -44,8 +44,7 @@ 3 true - - + SHA256 @@ -65,18 +64,11 @@ sp0.test-nemlog-in.dk sp1.test-nemlog-in.dk true - + - - Nets DanID A/S - Morten - Bech - mdbec@nets.eu - 4 - @@ -109,6 +101,11 @@ + + + + + diff --git a/src/dk.nita.saml20/WebsiteDemo/WebsiteDemo.csproj b/src/dk.nita.saml20/WebsiteDemo/WebsiteDemo.csproj index a545bb4..e996f46 100644 --- a/src/dk.nita.saml20/WebsiteDemo/WebsiteDemo.csproj +++ b/src/dk.nita.saml20/WebsiteDemo/WebsiteDemo.csproj @@ -128,7 +128,8 @@ - + + Designer diff --git a/src/dk.nita.saml20/WebsiteDemo/idp-metadata/test-devtest4-idp-metadata.xml b/src/dk.nita.saml20/WebsiteDemo/idp-metadata/oiosaml3-idp-devtest4-inttest-25-11-26.xml similarity index 62% rename from src/dk.nita.saml20/WebsiteDemo/idp-metadata/test-devtest4-idp-metadata.xml rename to src/dk.nita.saml20/WebsiteDemo/idp-metadata/oiosaml3-idp-devtest4-inttest-25-11-26.xml index 850cc49..197f764 100644 --- a/src/dk.nita.saml20/WebsiteDemo/idp-metadata/test-devtest4-idp-metadata.xml +++ b/src/dk.nita.saml20/WebsiteDemo/idp-metadata/oiosaml3-idp-devtest4-inttest-25-11-26.xml @@ -3,41 +3,43 @@ - MIIGYjCCBUqgAwIBAgIEX6YiGjANBgkqhkiG9w0BAQsFADBJMQswCQYDVQQGEwJE - SzESMBAGA1UECgwJVFJVU1QyNDA4MSYwJAYDVQQDDB1UUlVTVDI0MDggU3lzdGVt - dGVzdCBYWFhJViBDQTAeFw0yMjA5MTQwNzIyMTBaFw0yNTA5MTQwNzIxNTdaMIGa - MQswCQYDVQQGEwJESzExMC8GA1UECgwoRGlnaXRhbGlzZXJpbmdzc3R5cmVsc2Vu - IC8vIENWUjozNDA1MTE3ODFYMCAGA1UEBRMZQ1ZSOjM0MDUxMTc4LVVJRDo0MTIx - OTIwNDA0BgNVBAMMLURpZ2l0YWxpc2VyaW5nc3N0eXJlbHNlbiAtIE5lbUxvZy1p - biBJZFAgVGVzdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAIF+TEZl - CFr6gdnEN1CJj8cPzsaDAoReDGtf4x5NfOaXdpimBGtRwX6Rbv79fAzJe5Ci5Wwn - FdQrWk8ykXufyyjsKAtGc1EI4BRLXOW6slISZSN1GpI9l1DehE0I2J7t9Ov1crh7 - i1AnZDf58FRwLtnOI8FzO3bYvQoA3MNUMam58XwFtpnNbThacUfEkS4gAZx1sdND - zosAdyj4uKZGfCkEkp6XTs26EOJzTBmEl6bQxxqZyD1/hzS8YgIF0807MvOmGXze - oxP8IRF0bWNJtK9euCsUYWz0gfJtJqzgOFaPxEPrNo0ptvEjQHayZ81LvJXQocn7 - enl4Bix6AkUm02cCAwEAAaOCAv4wggL6MA4GA1UdDwEB/wQEAwIDuDCBlwYIKwYB - BQUHAQEEgYowgYcwPAYIKwYBBQUHMAGGMGh0dHA6Ly9vY3NwLnN5c3RlbXRlc3Qz - NC50cnVzdDI0MDguY29tL3Jlc3BvbmRlcjBHBggrBgEFBQcwAoY7aHR0cDovL3Yu - YWlhLnN5c3RlbXRlc3QzNC50cnVzdDI0MDguY29tL3N5c3RlbXRlc3QzNC1jYS5j - ZXIwggEgBgNVHSAEggEXMIIBEzCCAQ8GDSsGAQQBgfRRAgQGAwUwgf0wLwYIKwYB - BQUHAgEWI2h0dHA6Ly93d3cudHJ1c3QyNDA4LmNvbS9yZXBvc2l0b3J5MIHJBggr - BgEFBQcCAjCBvDAMFgVEYW5JRDADAgEBGoGrRGFuSUQgdGVzdCBjZXJ0aWZpa2F0 - ZXIgZnJhIGRlbm5lIENBIHVkc3RlZGVzIHVuZGVyIE9JRCAxLjMuNi4xLjQuMS4z - MTMxMy4yLjQuNi4zLjUuIERhbklEIHRlc3QgY2VydGlmaWNhdGVzIGZyb20gdGhp - cyBDQSBhcmUgaXNzdWVkIHVuZGVyIE9JRCAxLjMuNi4xLjQuMS4zMTMxMy4yLjQu - Ni4zLjUuMC8GA1UdEQQoMCaBJHRob21hcy5ueW1hbmRAZXh0ZXJuYWwubmV4aWdy - b3VwLmNvbTCBrQYDVR0fBIGlMIGiMDygOqA4hjZodHRwOi8vY3JsLnN5c3RlbXRl - c3QzNC50cnVzdDI0MDguY29tL3N5c3RlbXRlc3QzNC5jcmwwYqBgoF6kXDBaMQsw - CQYDVQQGEwJESzESMBAGA1UECgwJVFJVU1QyNDA4MSYwJAYDVQQDDB1UUlVTVDI0 - MDggU3lzdGVtdGVzdCBYWFhJViBDQTEPMA0GA1UEAwwGQ1JMNTc4MB8GA1UdIwQY - MBaAFM1saJc5chmkNatk6vQRo4GH+Gk7MB0GA1UdDgQWBBTkIBjQrTbrUa+YkuWT - mQcyrcaAlDAJBgNVHRMEAjAAMA0GCSqGSIb3DQEBCwUAA4IBAQCltmRhlf28jwPZ - nKz3exV2SotGGzmijDrK/1gndcx5ld8C556CjB8k3UplHSGJ1Sw60LGylvi33lsZ - 6kLL7lIEtzokMFXouNFwIA5+b6/GF5r7G3hvxiyrzkZnRT7DCznV5cNtlGlZC4yM - TQK4czYLnGGWutNtsKnrWMDoLsmHewNBetgPNt8hep/g3Xx5903gcOaitfT0VQkt - iVZvLzveuqitWkHedzwVj+1QlBBIxaR+zmm0JccPIYUCv3xaI+TSDsOY1ROzkDaX - uoHghyNk7qwsMPdnY50NmmAo68mnuEC7utRK/OqkGQ6UULHU9OzWxGzVljcQ5QLz - Blt+6WFR + + MIIGjDCCBMCgAwIBAgIUaGLv8eOYx3cubJyI3ymai6tAXCowQQYJKoZIhvcNAQEK + MDSgDzANBglghkgBZQMEAgEFAKEcMBoGCSqGSIb3DQEBCDANBglghkgBZQMEAgEF + AKIDAgEgMGsxLTArBgNVBAMMJERlbiBEYW5za2UgU3RhdCBPQ0VTIHVkc3RlZGVu + ZGUtQ0EgMTETMBEGA1UECwwKVGVzdCAtIGN0aTEYMBYGA1UECgwPRGVuIERhbnNr + ZSBTdGF0MQswCQYDVQQGEwJESzAeFw0yNTA4MjAxMzQxNDBaFw0yODA4MTkxMzQx + MzlaMIGhMR0wGwYDVQQDDBROZW1Mb2ctaW4gSWRQIC0gVGVzdDE3MDUGA1UEBRMu + VUk6REstTzpHOmEwNDBmZTI2LWNlNzgtNDMyOC1hYzBlLTI5ZWViMTJmNDZkZjEh + MB8GA1UECgwYRGlnaXRhbGlzZXJpbmdzc3R5cmVsc2VuMRcwFQYDVQRhDA5OVFJE + Sy0zNDA1MTE3ODELMAkGA1UEBhMCREswggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAw + ggGKAoIBgQCVUzcmIfK0NbJEmAQ7kFOTmXs1mkSHF0LAEFq7Ne8vpNz2H+0F5IyW + CwsBi3SByPTAEIClbIT6rLFBoMmIwjfRmAXd68zW7NYwR0N8PcR/hvtoCR1tW2Ju + KhQlKbWlaYLRvvvS3r5giIjHgEXpmv42caB76eYE3J2qWPaACOIRMXky1vCmbQpE + wqJr0S9+QDtMYh5ypVk1zX9rrY2TBbienruISBF1090uuzEQZtfiq9nZaBQAJZFl + cYLftepSZXW4QgJjWH6BhMrd4nvcz17WeabG3AhhKHvOUDukJgKMzQd/OcS1tY13 + P7soMeT8D8h5bCnNDoCfqM/5mgxgxZZXnjJhzOCY+MdrXXBRST2uQLNg0gl/Lgqm + EKk0izQaMtNauR+5fFHSJMN23Ga6fAmHMlyEj+5JhGeScRvIBp9tPERPhRF0MdEj + obbcweMRWqurJYsdo9cIHwrL8WIgQGhQRUrKBu9VPZQTtVs3dn3cxZIJ3axu53hW + EKRwqw4UoasCAwEAAaOCAYcwggGDMAwGA1UdEwEB/wQCMAAwHwYDVR0jBBgwFoAU + fyif2XGZQuJ159c1di5NCCVtdl4wewYIKwYBBQUHAQEEbzBtMEMGCCsGAQUFBzAC + hjdodHRwOi8vY2ExLmN0aS1nb3YuZGsvb2Nlcy9pc3N1aW5nLzEvY2FjZXJ0L2lz + c3VpbmcuY2VyMCYGCCsGAQUFBzABhhpodHRwOi8vY2ExLmN0aS1nb3YuZGsvb2Nz + cDAiBgNVHSAEGzAZMAgGBgQAj3oBATANBgsqgVCBKQEBAQMHATA7BggrBgEFBQcB + AwQvMC0wKwYIKwYBBQUHCwIwHwYHBACL7EkBAjAUhhJodHRwczovL3VpZC5nb3Yu + ZGswRQYDVR0fBD4wPDA6oDigNoY0aHR0cDovL2NhMS5jdGktZ292LmRrL29jZXMv + aXNzdWluZy8xL2NybC9pc3N1aW5nLmNybDAdBgNVHQ4EFgQU9KSlGZd1HK7yFmo+ + zohr4oq6LLwwDgYDVR0PAQH/BAQDAgWgMEEGCSqGSIb3DQEBCjA0oA8wDQYJYIZI + AWUDBAIBBQChHDAaBgkqhkiG9w0BAQgwDQYJYIZIAWUDBAIBBQCiAwIBIAOCAYEA + Pt4QGIebeY3idMN6xPUQUBwYeiIjhtxqo2O9BHELEQ8Vp9fuBiExT286i1nNbd6T + BgFFuUPh2kuwUqAj4YfaG7aSiCToJrTuaxBGlMI9nci2l5VDJ/1/lVVT/OkMLgR9 + xVXWSi8KFT8U9S+E1THE+G1YSNnt50yRDmqGNtG1XcaXQeu2Q4IcjMc2nf7NcGzG + widsKnBv0nNXwoYnh2ZLWPjQAgQzM3EYdZmEqaCrscYDFRbh4/T3TYjOo64N4rYZ + WTR+4/poz/29tyfVBWnr3rLuJH2q0kaiFVSXRHXoqOpCDUTVwsULShjmAHcPruQK + 7mRK1NQcwJtm0HQNWKUxizqc1pA38/9tU2vkQv+OxEEwHnCRK4XkLCJ8ZKCV5+c7 + AehhTLtDHqsA93+8afgrTLe+kWEO+xRgOJxKV9TnqkvnYiG8BtCOcb4+6yUMGAoO + PULVKywIzutRsHYjZptCkuggBqNztSFU/DUd6SpSxf1MGfeh4SC4yPNvKQ+5fo7S + @@ -82,41 +84,43 @@ - MIIGYjCCBUqgAwIBAgIEX6YiGjANBgkqhkiG9w0BAQsFADBJMQswCQYDVQQGEwJE - SzESMBAGA1UECgwJVFJVU1QyNDA4MSYwJAYDVQQDDB1UUlVTVDI0MDggU3lzdGVt - dGVzdCBYWFhJViBDQTAeFw0yMjA5MTQwNzIyMTBaFw0yNTA5MTQwNzIxNTdaMIGa - MQswCQYDVQQGEwJESzExMC8GA1UECgwoRGlnaXRhbGlzZXJpbmdzc3R5cmVsc2Vu - IC8vIENWUjozNDA1MTE3ODFYMCAGA1UEBRMZQ1ZSOjM0MDUxMTc4LVVJRDo0MTIx - OTIwNDA0BgNVBAMMLURpZ2l0YWxpc2VyaW5nc3N0eXJlbHNlbiAtIE5lbUxvZy1p - biBJZFAgVGVzdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAIF+TEZl - CFr6gdnEN1CJj8cPzsaDAoReDGtf4x5NfOaXdpimBGtRwX6Rbv79fAzJe5Ci5Wwn - FdQrWk8ykXufyyjsKAtGc1EI4BRLXOW6slISZSN1GpI9l1DehE0I2J7t9Ov1crh7 - i1AnZDf58FRwLtnOI8FzO3bYvQoA3MNUMam58XwFtpnNbThacUfEkS4gAZx1sdND - zosAdyj4uKZGfCkEkp6XTs26EOJzTBmEl6bQxxqZyD1/hzS8YgIF0807MvOmGXze - oxP8IRF0bWNJtK9euCsUYWz0gfJtJqzgOFaPxEPrNo0ptvEjQHayZ81LvJXQocn7 - enl4Bix6AkUm02cCAwEAAaOCAv4wggL6MA4GA1UdDwEB/wQEAwIDuDCBlwYIKwYB - BQUHAQEEgYowgYcwPAYIKwYBBQUHMAGGMGh0dHA6Ly9vY3NwLnN5c3RlbXRlc3Qz - NC50cnVzdDI0MDguY29tL3Jlc3BvbmRlcjBHBggrBgEFBQcwAoY7aHR0cDovL3Yu - YWlhLnN5c3RlbXRlc3QzNC50cnVzdDI0MDguY29tL3N5c3RlbXRlc3QzNC1jYS5j - ZXIwggEgBgNVHSAEggEXMIIBEzCCAQ8GDSsGAQQBgfRRAgQGAwUwgf0wLwYIKwYB - BQUHAgEWI2h0dHA6Ly93d3cudHJ1c3QyNDA4LmNvbS9yZXBvc2l0b3J5MIHJBggr - BgEFBQcCAjCBvDAMFgVEYW5JRDADAgEBGoGrRGFuSUQgdGVzdCBjZXJ0aWZpa2F0 - ZXIgZnJhIGRlbm5lIENBIHVkc3RlZGVzIHVuZGVyIE9JRCAxLjMuNi4xLjQuMS4z - MTMxMy4yLjQuNi4zLjUuIERhbklEIHRlc3QgY2VydGlmaWNhdGVzIGZyb20gdGhp - cyBDQSBhcmUgaXNzdWVkIHVuZGVyIE9JRCAxLjMuNi4xLjQuMS4zMTMxMy4yLjQu - Ni4zLjUuMC8GA1UdEQQoMCaBJHRob21hcy5ueW1hbmRAZXh0ZXJuYWwubmV4aWdy - b3VwLmNvbTCBrQYDVR0fBIGlMIGiMDygOqA4hjZodHRwOi8vY3JsLnN5c3RlbXRl - c3QzNC50cnVzdDI0MDguY29tL3N5c3RlbXRlc3QzNC5jcmwwYqBgoF6kXDBaMQsw - CQYDVQQGEwJESzESMBAGA1UECgwJVFJVU1QyNDA4MSYwJAYDVQQDDB1UUlVTVDI0 - MDggU3lzdGVtdGVzdCBYWFhJViBDQTEPMA0GA1UEAwwGQ1JMNTc4MB8GA1UdIwQY - MBaAFM1saJc5chmkNatk6vQRo4GH+Gk7MB0GA1UdDgQWBBTkIBjQrTbrUa+YkuWT - mQcyrcaAlDAJBgNVHRMEAjAAMA0GCSqGSIb3DQEBCwUAA4IBAQCltmRhlf28jwPZ - nKz3exV2SotGGzmijDrK/1gndcx5ld8C556CjB8k3UplHSGJ1Sw60LGylvi33lsZ - 6kLL7lIEtzokMFXouNFwIA5+b6/GF5r7G3hvxiyrzkZnRT7DCznV5cNtlGlZC4yM - TQK4czYLnGGWutNtsKnrWMDoLsmHewNBetgPNt8hep/g3Xx5903gcOaitfT0VQkt - iVZvLzveuqitWkHedzwVj+1QlBBIxaR+zmm0JccPIYUCv3xaI+TSDsOY1ROzkDaX - uoHghyNk7qwsMPdnY50NmmAo68mnuEC7utRK/OqkGQ6UULHU9OzWxGzVljcQ5QLz - Blt+6WFR + + MIIGjDCCBMCgAwIBAgIUaGLv8eOYx3cubJyI3ymai6tAXCowQQYJKoZIhvcNAQEK + MDSgDzANBglghkgBZQMEAgEFAKEcMBoGCSqGSIb3DQEBCDANBglghkgBZQMEAgEF + AKIDAgEgMGsxLTArBgNVBAMMJERlbiBEYW5za2UgU3RhdCBPQ0VTIHVkc3RlZGVu + ZGUtQ0EgMTETMBEGA1UECwwKVGVzdCAtIGN0aTEYMBYGA1UECgwPRGVuIERhbnNr + ZSBTdGF0MQswCQYDVQQGEwJESzAeFw0yNTA4MjAxMzQxNDBaFw0yODA4MTkxMzQx + MzlaMIGhMR0wGwYDVQQDDBROZW1Mb2ctaW4gSWRQIC0gVGVzdDE3MDUGA1UEBRMu + VUk6REstTzpHOmEwNDBmZTI2LWNlNzgtNDMyOC1hYzBlLTI5ZWViMTJmNDZkZjEh + MB8GA1UECgwYRGlnaXRhbGlzZXJpbmdzc3R5cmVsc2VuMRcwFQYDVQRhDA5OVFJE + Sy0zNDA1MTE3ODELMAkGA1UEBhMCREswggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAw + ggGKAoIBgQCVUzcmIfK0NbJEmAQ7kFOTmXs1mkSHF0LAEFq7Ne8vpNz2H+0F5IyW + CwsBi3SByPTAEIClbIT6rLFBoMmIwjfRmAXd68zW7NYwR0N8PcR/hvtoCR1tW2Ju + KhQlKbWlaYLRvvvS3r5giIjHgEXpmv42caB76eYE3J2qWPaACOIRMXky1vCmbQpE + wqJr0S9+QDtMYh5ypVk1zX9rrY2TBbienruISBF1090uuzEQZtfiq9nZaBQAJZFl + cYLftepSZXW4QgJjWH6BhMrd4nvcz17WeabG3AhhKHvOUDukJgKMzQd/OcS1tY13 + P7soMeT8D8h5bCnNDoCfqM/5mgxgxZZXnjJhzOCY+MdrXXBRST2uQLNg0gl/Lgqm + EKk0izQaMtNauR+5fFHSJMN23Ga6fAmHMlyEj+5JhGeScRvIBp9tPERPhRF0MdEj + obbcweMRWqurJYsdo9cIHwrL8WIgQGhQRUrKBu9VPZQTtVs3dn3cxZIJ3axu53hW + EKRwqw4UoasCAwEAAaOCAYcwggGDMAwGA1UdEwEB/wQCMAAwHwYDVR0jBBgwFoAU + fyif2XGZQuJ159c1di5NCCVtdl4wewYIKwYBBQUHAQEEbzBtMEMGCCsGAQUFBzAC + hjdodHRwOi8vY2ExLmN0aS1nb3YuZGsvb2Nlcy9pc3N1aW5nLzEvY2FjZXJ0L2lz + c3VpbmcuY2VyMCYGCCsGAQUFBzABhhpodHRwOi8vY2ExLmN0aS1nb3YuZGsvb2Nz + cDAiBgNVHSAEGzAZMAgGBgQAj3oBATANBgsqgVCBKQEBAQMHATA7BggrBgEFBQcB + AwQvMC0wKwYIKwYBBQUHCwIwHwYHBACL7EkBAjAUhhJodHRwczovL3VpZC5nb3Yu + ZGswRQYDVR0fBD4wPDA6oDigNoY0aHR0cDovL2NhMS5jdGktZ292LmRrL29jZXMv + aXNzdWluZy8xL2NybC9pc3N1aW5nLmNybDAdBgNVHQ4EFgQU9KSlGZd1HK7yFmo+ + zohr4oq6LLwwDgYDVR0PAQH/BAQDAgWgMEEGCSqGSIb3DQEBCjA0oA8wDQYJYIZI + AWUDBAIBBQChHDAaBgkqhkiG9w0BAQgwDQYJYIZIAWUDBAIBBQCiAwIBIAOCAYEA + Pt4QGIebeY3idMN6xPUQUBwYeiIjhtxqo2O9BHELEQ8Vp9fuBiExT286i1nNbd6T + BgFFuUPh2kuwUqAj4YfaG7aSiCToJrTuaxBGlMI9nci2l5VDJ/1/lVVT/OkMLgR9 + xVXWSi8KFT8U9S+E1THE+G1YSNnt50yRDmqGNtG1XcaXQeu2Q4IcjMc2nf7NcGzG + widsKnBv0nNXwoYnh2ZLWPjQAgQzM3EYdZmEqaCrscYDFRbh4/T3TYjOo64N4rYZ + WTR+4/poz/29tyfVBWnr3rLuJH2q0kaiFVSXRHXoqOpCDUTVwsULShjmAHcPruQK + 7mRK1NQcwJtm0HQNWKUxizqc1pA38/9tU2vkQv+OxEEwHnCRK4XkLCJ8ZKCV5+c7 + AehhTLtDHqsA93+8afgrTLe+kWEO+xRgOJxKV9TnqkvnYiG8BtCOcb4+6yUMGAoO + PULVKywIzutRsHYjZptCkuggBqNztSFU/DUd6SpSxf1MGfeh4SC4yPNvKQ+5fo7S + diff --git a/src/dk.nita.saml20/WebsiteDemo/idp-metadata/oiosaml3-idp-inttest-25-11-28.xml b/src/dk.nita.saml20/WebsiteDemo/idp-metadata/oiosaml3-idp-inttest-25-11-28.xml new file mode 100644 index 0000000..cd25618 --- /dev/null +++ b/src/dk.nita.saml20/WebsiteDemo/idp-metadata/oiosaml3-idp-inttest-25-11-28.xml @@ -0,0 +1,199 @@ + + + + + + + MIIGjDCCBMCgAwIBAgIUaGLv8eOYx3cubJyI3ymai6tAXCowQQYJKoZIhvcNAQEK + MDSgDzANBglghkgBZQMEAgEFAKEcMBoGCSqGSIb3DQEBCDANBglghkgBZQMEAgEF + AKIDAgEgMGsxLTArBgNVBAMMJERlbiBEYW5za2UgU3RhdCBPQ0VTIHVkc3RlZGVu + ZGUtQ0EgMTETMBEGA1UECwwKVGVzdCAtIGN0aTEYMBYGA1UECgwPRGVuIERhbnNr + ZSBTdGF0MQswCQYDVQQGEwJESzAeFw0yNTA4MjAxMzQxNDBaFw0yODA4MTkxMzQx + MzlaMIGhMR0wGwYDVQQDDBROZW1Mb2ctaW4gSWRQIC0gVGVzdDE3MDUGA1UEBRMu + VUk6REstTzpHOmEwNDBmZTI2LWNlNzgtNDMyOC1hYzBlLTI5ZWViMTJmNDZkZjEh + MB8GA1UECgwYRGlnaXRhbGlzZXJpbmdzc3R5cmVsc2VuMRcwFQYDVQRhDA5OVFJE + Sy0zNDA1MTE3ODELMAkGA1UEBhMCREswggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAw + ggGKAoIBgQCVUzcmIfK0NbJEmAQ7kFOTmXs1mkSHF0LAEFq7Ne8vpNz2H+0F5IyW + CwsBi3SByPTAEIClbIT6rLFBoMmIwjfRmAXd68zW7NYwR0N8PcR/hvtoCR1tW2Ju + KhQlKbWlaYLRvvvS3r5giIjHgEXpmv42caB76eYE3J2qWPaACOIRMXky1vCmbQpE + wqJr0S9+QDtMYh5ypVk1zX9rrY2TBbienruISBF1090uuzEQZtfiq9nZaBQAJZFl + cYLftepSZXW4QgJjWH6BhMrd4nvcz17WeabG3AhhKHvOUDukJgKMzQd/OcS1tY13 + P7soMeT8D8h5bCnNDoCfqM/5mgxgxZZXnjJhzOCY+MdrXXBRST2uQLNg0gl/Lgqm + EKk0izQaMtNauR+5fFHSJMN23Ga6fAmHMlyEj+5JhGeScRvIBp9tPERPhRF0MdEj + obbcweMRWqurJYsdo9cIHwrL8WIgQGhQRUrKBu9VPZQTtVs3dn3cxZIJ3axu53hW + EKRwqw4UoasCAwEAAaOCAYcwggGDMAwGA1UdEwEB/wQCMAAwHwYDVR0jBBgwFoAU + fyif2XGZQuJ159c1di5NCCVtdl4wewYIKwYBBQUHAQEEbzBtMEMGCCsGAQUFBzAC + hjdodHRwOi8vY2ExLmN0aS1nb3YuZGsvb2Nlcy9pc3N1aW5nLzEvY2FjZXJ0L2lz + c3VpbmcuY2VyMCYGCCsGAQUFBzABhhpodHRwOi8vY2ExLmN0aS1nb3YuZGsvb2Nz + cDAiBgNVHSAEGzAZMAgGBgQAj3oBATANBgsqgVCBKQEBAQMHATA7BggrBgEFBQcB + AwQvMC0wKwYIKwYBBQUHCwIwHwYHBACL7EkBAjAUhhJodHRwczovL3VpZC5nb3Yu + ZGswRQYDVR0fBD4wPDA6oDigNoY0aHR0cDovL2NhMS5jdGktZ292LmRrL29jZXMv + aXNzdWluZy8xL2NybC9pc3N1aW5nLmNybDAdBgNVHQ4EFgQU9KSlGZd1HK7yFmo+ + zohr4oq6LLwwDgYDVR0PAQH/BAQDAgWgMEEGCSqGSIb3DQEBCjA0oA8wDQYJYIZI + AWUDBAIBBQChHDAaBgkqhkiG9w0BAQgwDQYJYIZIAWUDBAIBBQCiAwIBIAOCAYEA + Pt4QGIebeY3idMN6xPUQUBwYeiIjhtxqo2O9BHELEQ8Vp9fuBiExT286i1nNbd6T + BgFFuUPh2kuwUqAj4YfaG7aSiCToJrTuaxBGlMI9nci2l5VDJ/1/lVVT/OkMLgR9 + xVXWSi8KFT8U9S+E1THE+G1YSNnt50yRDmqGNtG1XcaXQeu2Q4IcjMc2nf7NcGzG + widsKnBv0nNXwoYnh2ZLWPjQAgQzM3EYdZmEqaCrscYDFRbh4/T3TYjOo64N4rYZ + WTR+4/poz/29tyfVBWnr3rLuJH2q0kaiFVSXRHXoqOpCDUTVwsULShjmAHcPruQK + 7mRK1NQcwJtm0HQNWKUxizqc1pA38/9tU2vkQv+OxEEwHnCRK4XkLCJ8ZKCV5+c7 + AehhTLtDHqsA93+8afgrTLe+kWEO+xRgOJxKV9TnqkvnYiG8BtCOcb4+6yUMGAoO + PULVKywIzutRsHYjZptCkuggBqNztSFU/DUd6SpSxf1MGfeh4SC4yPNvKQ+5fo7S + + + + + + + urn:oasis:names:tc:SAML:2.0:nameid-format:transient + urn:oasis:names:tc:SAML:2.0:nameid-format:persistent + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + MIIGjDCCBMCgAwIBAgIUaGLv8eOYx3cubJyI3ymai6tAXCowQQYJKoZIhvcNAQEK + MDSgDzANBglghkgBZQMEAgEFAKEcMBoGCSqGSIb3DQEBCDANBglghkgBZQMEAgEF + AKIDAgEgMGsxLTArBgNVBAMMJERlbiBEYW5za2UgU3RhdCBPQ0VTIHVkc3RlZGVu + ZGUtQ0EgMTETMBEGA1UECwwKVGVzdCAtIGN0aTEYMBYGA1UECgwPRGVuIERhbnNr + ZSBTdGF0MQswCQYDVQQGEwJESzAeFw0yNTA4MjAxMzQxNDBaFw0yODA4MTkxMzQx + MzlaMIGhMR0wGwYDVQQDDBROZW1Mb2ctaW4gSWRQIC0gVGVzdDE3MDUGA1UEBRMu + VUk6REstTzpHOmEwNDBmZTI2LWNlNzgtNDMyOC1hYzBlLTI5ZWViMTJmNDZkZjEh + MB8GA1UECgwYRGlnaXRhbGlzZXJpbmdzc3R5cmVsc2VuMRcwFQYDVQRhDA5OVFJE + Sy0zNDA1MTE3ODELMAkGA1UEBhMCREswggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAw + ggGKAoIBgQCVUzcmIfK0NbJEmAQ7kFOTmXs1mkSHF0LAEFq7Ne8vpNz2H+0F5IyW + CwsBi3SByPTAEIClbIT6rLFBoMmIwjfRmAXd68zW7NYwR0N8PcR/hvtoCR1tW2Ju + KhQlKbWlaYLRvvvS3r5giIjHgEXpmv42caB76eYE3J2qWPaACOIRMXky1vCmbQpE + wqJr0S9+QDtMYh5ypVk1zX9rrY2TBbienruISBF1090uuzEQZtfiq9nZaBQAJZFl + cYLftepSZXW4QgJjWH6BhMrd4nvcz17WeabG3AhhKHvOUDukJgKMzQd/OcS1tY13 + P7soMeT8D8h5bCnNDoCfqM/5mgxgxZZXnjJhzOCY+MdrXXBRST2uQLNg0gl/Lgqm + EKk0izQaMtNauR+5fFHSJMN23Ga6fAmHMlyEj+5JhGeScRvIBp9tPERPhRF0MdEj + obbcweMRWqurJYsdo9cIHwrL8WIgQGhQRUrKBu9VPZQTtVs3dn3cxZIJ3axu53hW + EKRwqw4UoasCAwEAAaOCAYcwggGDMAwGA1UdEwEB/wQCMAAwHwYDVR0jBBgwFoAU + fyif2XGZQuJ159c1di5NCCVtdl4wewYIKwYBBQUHAQEEbzBtMEMGCCsGAQUFBzAC + hjdodHRwOi8vY2ExLmN0aS1nb3YuZGsvb2Nlcy9pc3N1aW5nLzEvY2FjZXJ0L2lz + c3VpbmcuY2VyMCYGCCsGAQUFBzABhhpodHRwOi8vY2ExLmN0aS1nb3YuZGsvb2Nz + cDAiBgNVHSAEGzAZMAgGBgQAj3oBATANBgsqgVCBKQEBAQMHATA7BggrBgEFBQcB + AwQvMC0wKwYIKwYBBQUHCwIwHwYHBACL7EkBAjAUhhJodHRwczovL3VpZC5nb3Yu + ZGswRQYDVR0fBD4wPDA6oDigNoY0aHR0cDovL2NhMS5jdGktZ292LmRrL29jZXMv + aXNzdWluZy8xL2NybC9pc3N1aW5nLmNybDAdBgNVHQ4EFgQU9KSlGZd1HK7yFmo+ + zohr4oq6LLwwDgYDVR0PAQH/BAQDAgWgMEEGCSqGSIb3DQEBCjA0oA8wDQYJYIZI + AWUDBAIBBQChHDAaBgkqhkiG9w0BAQgwDQYJYIZIAWUDBAIBBQCiAwIBIAOCAYEA + Pt4QGIebeY3idMN6xPUQUBwYeiIjhtxqo2O9BHELEQ8Vp9fuBiExT286i1nNbd6T + BgFFuUPh2kuwUqAj4YfaG7aSiCToJrTuaxBGlMI9nci2l5VDJ/1/lVVT/OkMLgR9 + xVXWSi8KFT8U9S+E1THE+G1YSNnt50yRDmqGNtG1XcaXQeu2Q4IcjMc2nf7NcGzG + widsKnBv0nNXwoYnh2ZLWPjQAgQzM3EYdZmEqaCrscYDFRbh4/T3TYjOo64N4rYZ + WTR+4/poz/29tyfVBWnr3rLuJH2q0kaiFVSXRHXoqOpCDUTVwsULShjmAHcPruQK + 7mRK1NQcwJtm0HQNWKUxizqc1pA38/9tU2vkQv+OxEEwHnCRK4XkLCJ8ZKCV5+c7 + AehhTLtDHqsA93+8afgrTLe+kWEO+xRgOJxKV9TnqkvnYiG8BtCOcb4+6yUMGAoO + PULVKywIzutRsHYjZptCkuggBqNztSFU/DUd6SpSxf1MGfeh4SC4yPNvKQ+5fo7S + + + + + + urn:oasis:names:tc:SAML:2.0:nameid-format:transient + urn:oasis:names:tc:SAML:2.0:nameid-format:persistent + + + + + + + + + + + + + + + + + + + + + + NemLog-in + + + nemlogin@digst.dk + + + diff --git a/src/dk.nita.saml20/dk.nita.saml20/Bindings/HttpRedirectBindingBuilder.cs b/src/dk.nita.saml20/dk.nita.saml20/Bindings/HttpRedirectBindingBuilder.cs index 1d2bc8f..2ad1ad6 100644 --- a/src/dk.nita.saml20/dk.nita.saml20/Bindings/HttpRedirectBindingBuilder.cs +++ b/src/dk.nita.saml20/dk.nita.saml20/Bindings/HttpRedirectBindingBuilder.cs @@ -78,8 +78,9 @@ public AsymmetricAlgorithm signingKey set { // Check if the key is of a supported type. [SAMLBind] sect. 3.4.4.1 specifies this. - if (!(value is RSACryptoServiceProvider || value == null)) - throw new ArgumentException("Signing key must be an instance of RSACryptoServiceProvider."); + // Accept any RSA implementation (RSACryptoServiceProvider for legacy CSP keys, RSACng for CNG keys). + if (!(value is RSA || value == null)) + throw new ArgumentException("Signing key must be an instance of RSA."); _signingKey = value; } diff --git a/src/dk.nita.saml20/dk.nita.saml20/Bindings/SignatureProviders/RsaSha1SignatureProvider.cs b/src/dk.nita.saml20/dk.nita.saml20/Bindings/SignatureProviders/RsaSha1SignatureProvider.cs index 11650e2..032c2d9 100644 --- a/src/dk.nita.saml20/dk.nita.saml20/Bindings/SignatureProviders/RsaSha1SignatureProvider.cs +++ b/src/dk.nita.saml20/dk.nita.saml20/Bindings/SignatureProviders/RsaSha1SignatureProvider.cs @@ -7,16 +7,7 @@ internal class RsaSha1SignatureProvider : SignatureProvider { public override string SignatureUri => SignedXml.XmlDsigRSASHA1Url; public override string DigestUri => SignedXml.XmlDsigSHA1Url; - protected override byte[] SignDataIntern(RSACryptoServiceProvider key, byte[] data) - { - return key.SignData(data, new SHA1CryptoServiceProvider()); - } - - protected override bool VerifySignatureIntern(RSACryptoServiceProvider key, byte[] data, byte[] signature) - { - var hash = new SHA1Managed().ComputeHash(data); - return ((RSACryptoServiceProvider) key).VerifyHash(hash, "SHA1", signature); - } + protected override HashAlgorithmName HashName => HashAlgorithmName.SHA1; } } \ No newline at end of file diff --git a/src/dk.nita.saml20/dk.nita.saml20/Bindings/SignatureProviders/RsaSha256SignatureProvider.cs b/src/dk.nita.saml20/dk.nita.saml20/Bindings/SignatureProviders/RsaSha256SignatureProvider.cs index 6185ca7..3d4d3e2 100644 --- a/src/dk.nita.saml20/dk.nita.saml20/Bindings/SignatureProviders/RsaSha256SignatureProvider.cs +++ b/src/dk.nita.saml20/dk.nita.saml20/Bindings/SignatureProviders/RsaSha256SignatureProvider.cs @@ -7,15 +7,6 @@ internal class RsaSha256SignatureProvider : SignatureProvider { public override string SignatureUri => SignedXml.XmlDsigRSASHA256Url; public override string DigestUri => SignedXml.XmlDsigSHA256Url; - protected override byte[] SignDataIntern(RSACryptoServiceProvider key, byte[] data) - { - return key.SignData(data, new SHA256CryptoServiceProvider()); - } - - protected override bool VerifySignatureIntern(RSACryptoServiceProvider key, byte[] data, byte[] signature) - { - var hash = new SHA256Managed().ComputeHash(data); - return ((RSACryptoServiceProvider)key).VerifyHash(hash, "SHA256", signature); - } + protected override HashAlgorithmName HashName => HashAlgorithmName.SHA256; } } \ No newline at end of file diff --git a/src/dk.nita.saml20/dk.nita.saml20/Bindings/SignatureProviders/RsaSha512SignatureProvider.cs b/src/dk.nita.saml20/dk.nita.saml20/Bindings/SignatureProviders/RsaSha512SignatureProvider.cs index c2b1b86..a081f17 100644 --- a/src/dk.nita.saml20/dk.nita.saml20/Bindings/SignatureProviders/RsaSha512SignatureProvider.cs +++ b/src/dk.nita.saml20/dk.nita.saml20/Bindings/SignatureProviders/RsaSha512SignatureProvider.cs @@ -7,15 +7,6 @@ internal class RsaSha512SignatureProvider : SignatureProvider { public override string SignatureUri => SignedXml.XmlDsigRSASHA512Url; public override string DigestUri => SignedXml.XmlDsigSHA512Url; - protected override byte[] SignDataIntern(RSACryptoServiceProvider key, byte[] data) - { - return key.SignData(data, new SHA512CryptoServiceProvider()); - } - - protected override bool VerifySignatureIntern(RSACryptoServiceProvider key, byte[] data, byte[] signature) - { - var hash = new SHA512Managed().ComputeHash(data); - return ((RSACryptoServiceProvider)key).VerifyHash(hash, "SHA512", signature); - } + protected override HashAlgorithmName HashName => HashAlgorithmName.SHA512; } } \ No newline at end of file diff --git a/src/dk.nita.saml20/dk.nita.saml20/Bindings/SignatureProviders/SignatureProvider.cs b/src/dk.nita.saml20/dk.nita.saml20/Bindings/SignatureProviders/SignatureProvider.cs index 8fed0a7..0b823a1 100644 --- a/src/dk.nita.saml20/dk.nita.saml20/Bindings/SignatureProviders/SignatureProvider.cs +++ b/src/dk.nita.saml20/dk.nita.saml20/Bindings/SignatureProviders/SignatureProvider.cs @@ -15,25 +15,22 @@ internal abstract class SignatureProvider : ISignatureProvider public byte[] SignData(AsymmetricAlgorithm key, byte[] data) { - var rsa = (RSACryptoServiceProvider)key; + var rsa = ToSha2CapableRsa(key); - rsa = ConvertProviderType(rsa); - - return SignDataIntern(rsa, data); + return rsa.SignData(data, HashName, RSASignaturePadding.Pkcs1); } - protected abstract byte[] SignDataIntern(RSACryptoServiceProvider key, byte[] data); - public bool VerifySignature(AsymmetricAlgorithm key, byte[] data, byte[] signature) { - var rsa = (RSACryptoServiceProvider)key; - - rsa = ConvertProviderType(rsa); + var rsa = ToSha2CapableRsa(key); - return VerifySignatureIntern(rsa, data, signature); + return rsa.VerifyData(data, signature, HashName, RSASignaturePadding.Pkcs1); } - protected abstract bool VerifySignatureIntern(RSACryptoServiceProvider key, byte[] data, byte[] signature); + /// + /// The hash algorithm this provider uses when signing/verifying raw data such as the HTTP-Redirect query. + /// + protected abstract HashAlgorithmName HashName { get; } public void SignAssertion(XmlDocument doc, string id, X509Certificate2 cert) { @@ -72,26 +69,52 @@ private SignedXml Sign(XmlDocument doc, string id, X509Certificate2 cert) return signedXml; } - private static RSACryptoServiceProvider ConvertProviderType(RSACryptoServiceProvider rsa) + /// + /// Returns an instance guaranteed to support SHA-2, keeping the signing/verification + /// path provider-agnostic: it works with modern CNG keys () as well as legacy + /// CryptoAPI keys (). + /// + private static RSA ToSha2CapableRsa(AsymmetricAlgorithm key) { - // ProviderType == 1 is PROV_RSA_FULL provider type that only supports SHA1. Change it to PROV_RSA_AES=24 that supports SHA2 also. + var rsa = (RSA)key; + + // CNG keys already support SHA-2. + if (rsa is RSACng) + return rsa; + + var csp = rsa as RSACryptoServiceProvider; + if (csp == null) + return rsa; + + // Public keys (inbound signature verification): re-import into a CNG key, which supports + // SHA-2 regardless of the originating CSP provider type. + if (csp.PublicOnly) + { + var cng = new RSACng(); + cng.ImportParameters(csp.ExportParameters(false)); + return cng; + } + + // A private key backed by a legacy PROV_RSA_FULL (provider type 1) CSP only supports SHA-1. + // Reopen the same key container under PROV_RSA_AES (provider type 24), which supports SHA-2. // https://github.com/Microsoft/referencesource/blob/master/System.IdentityModel/System/IdentityModel/Tokens/X509AsymmetricSecurityKey.cs#L54 - if (rsa != null && rsa.CspKeyContainerInfo.ProviderType == 1) + if (csp.CspKeyContainerInfo.ProviderType == 1) { if (Trace.ShouldTrace(TraceEventType.Verbose)) + Trace.TraceData(TraceEventType.Verbose, "Reopened RSA private key under provider type 24 to enable SHA-2"); + + var cspParams = new CspParameters { - Trace.TraceData(TraceEventType.Verbose, - "Changed provider type from " + rsa.CspKeyContainerInfo.ProviderType + " to 24"); - } - CspParameters csp = new CspParameters(); - csp.ProviderType = 24; - csp.KeyContainerName = rsa.CspKeyContainerInfo.KeyContainerName; - csp.KeyNumber = (int)rsa.CspKeyContainerInfo.KeyNumber; - if (rsa.CspKeyContainerInfo.MachineKeyStore) - csp.Flags = CspProviderFlags.UseMachineKeyStore; - csp.Flags |= CspProviderFlags.UseExistingKey; - rsa = new RSACryptoServiceProvider(csp); + ProviderType = 24, + KeyContainerName = csp.CspKeyContainerInfo.KeyContainerName, + KeyNumber = (int)csp.CspKeyContainerInfo.KeyNumber + }; + if (csp.CspKeyContainerInfo.MachineKeyStore) + cspParams.Flags = CspProviderFlags.UseMachineKeyStore; + cspParams.Flags |= CspProviderFlags.UseExistingKey; + return new RSACryptoServiceProvider(cspParams); } + return rsa; } } diff --git a/src/dk.nita.saml20/dk.nita.saml20/Protocol/Saml20LogoutHandler.cs b/src/dk.nita.saml20/dk.nita.saml20/Protocol/Saml20LogoutHandler.cs index 57fdcb0..f2bda1d 100644 --- a/src/dk.nita.saml20/dk.nita.saml20/Protocol/Saml20LogoutHandler.cs +++ b/src/dk.nita.saml20/dk.nita.saml20/Protocol/Saml20LogoutHandler.cs @@ -1,6 +1,7 @@ using System; using System.Diagnostics; using System.IO; +using System.Security.Cryptography.X509Certificates; using System.Threading; using System.Web; using System.Web.Security; @@ -302,7 +303,7 @@ private void TransferClient(IDPEndPoint endpoint, HttpContext context) if (destination.Binding == SAMLBinding.REDIRECT) { HttpRedirectBindingBuilder builder = new HttpRedirectBindingBuilder(); - builder.signingKey = FederationConfig.GetConfig().GetFirstValidCertificate().PrivateKey; + builder.signingKey = FederationConfig.GetConfig().GetFirstValidCertificate().GetRSAPrivateKey(); request.Destination = destination.Url; request.Reason = Saml20Constants.Reasons.User; request.SubjectToLogOut.Value = Saml20PrincipalCache.GetSaml20AssertionLite().Subject.Value; @@ -589,7 +590,7 @@ private void HandleRequest(HttpContext context) HttpRedirectBindingBuilder builder = new HttpRedirectBindingBuilder(); builder.RelayState = context.Request.Params["RelayState"]; builder.Response = response.GetXml().OuterXml; - builder.signingKey = FederationConfig.GetConfig().GetFirstValidCertificate().PrivateKey; + builder.signingKey = FederationConfig.GetConfig().GetFirstValidCertificate().GetRSAPrivateKey(); builder.ShaHashingAlgorithm = shaHashingAlgorithm; string s = destination.Url + "?" + builder.ToQuery(); context.Response.Redirect(s, true); diff --git a/src/dk.nita.saml20/dk.nita.saml20/Protocol/Saml20SignonHandler.cs b/src/dk.nita.saml20/dk.nita.saml20/Protocol/Saml20SignonHandler.cs index 01c1b98..ce21363 100644 --- a/src/dk.nita.saml20/dk.nita.saml20/Protocol/Saml20SignonHandler.cs +++ b/src/dk.nita.saml20/dk.nita.saml20/Protocol/Saml20SignonHandler.cs @@ -409,7 +409,7 @@ private static Saml20EncryptedAssertion GetDecryptedAssertion(XmlElement elem) { var tryDecryptAssertion = new Func((certificate) => { - Saml20EncryptedAssertion decryptedAssertion = new Saml20EncryptedAssertion((RSA)certificate.PrivateKey); + Saml20EncryptedAssertion decryptedAssertion = new Saml20EncryptedAssertion(certificate.GetRSAPrivateKey()); decryptedAssertion.LoadXml(elem); decryptedAssertion.Decrypt(); return decryptedAssertion; @@ -893,7 +893,7 @@ private void TransferClient(IDPEndPoint idpEndpoint, Saml20AuthnRequest request, Trace.TraceData(TraceEventType.Information, string.Format(Tracing.SendAuthnRequest, Saml20Constants.ProtocolBindings.HTTP_Redirect, idpEndpoint.Id)); HttpRedirectBindingBuilder builder = new HttpRedirectBindingBuilder(); - builder.signingKey = _certificate.PrivateKey; + builder.signingKey = _certificate.GetRSAPrivateKey(); builder.Request = request.GetXml().OuterXml; builder.ShaHashingAlgorithm = shaHashingAlgorithm; string s = request.Destination + "?" + builder.ToQuery(); diff --git a/src/dk.nita.saml20/dk.nita.saml20/Saml20AttributeQuery.cs b/src/dk.nita.saml20/dk.nita.saml20/Saml20AttributeQuery.cs index f3acd69..bbd12a3 100644 --- a/src/dk.nita.saml20/dk.nita.saml20/Saml20AttributeQuery.cs +++ b/src/dk.nita.saml20/dk.nita.saml20/Saml20AttributeQuery.cs @@ -3,6 +3,7 @@ using System.Diagnostics; using System.IO; using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; using System.Web; using System.Xml; using dk.nita.saml20.Bindings; @@ -220,7 +221,7 @@ public void PerformQuery(HttpContext context, IDPEndPoint endPoint, string nameI { Saml20EncryptedAssertion ass = new Saml20EncryptedAssertion( - (RSA)FederationConfig.GetConfig().GetFirstValidCertificate().PrivateKey); + FederationConfig.GetConfig().GetFirstValidCertificate().GetRSAPrivateKey()); ass.LoadXml(xmlAssertion); ass.Decrypt(); xmlAssertion = ass.Assertion.DocumentElement;