Skip to content

Instantly share code, notes, and snippets.

@dbeinder
Last active September 15, 2022 02:51
Show Gist options
  • Save dbeinder/3f0339786fe75a197173b74bf6b809e7 to your computer and use it in GitHub Desktop.
Save dbeinder/3f0339786fe75a197173b74bf6b809e7 to your computer and use it in GitHub Desktop.
X509Chain platform differences, SslStreamCertificateContext test server
using System;
using System.Net;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
namespace X509Test
{
class Program
{
static string LeafPfx = @"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";
static string IntermediateCert = @"-----BEGIN CERTIFICATE-----
MIIFADCCA+igAwIBAgIBBzANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMx
EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT
HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVs
ZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTExMDUwMzA3MDAw
MFoXDTMxMDUwMzA3MDAwMFowgcYxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6
b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVj
aG5vbG9naWVzLCBJbmMuMTMwMQYDVQQLEypodHRwOi8vY2VydHMuc3RhcmZpZWxk
dGVjaC5jb20vcmVwb3NpdG9yeS8xNDAyBgNVBAMTK1N0YXJmaWVsZCBTZWN1cmUg
Q2VydGlmaWNhdGUgQXV0aG9yaXR5IC0gRzIwggEiMA0GCSqGSIb3DQEBAQUAA4IB
DwAwggEKAoIBAQDlkGZL7PlGcakgg77pbL9KyUhpgXVObST2yxcT+LBxWYR6ayuF
pDS1FuXLzOlBcCykLtb6Mn3hqN6UEKwxwcDYav9ZJ6t21vwLdGu4p64/xFT0tDFE
3ZNWjKRMXpuJyySDm+JXfbfYEh/JhW300YDxUJuHrtQLEAX7J7oobRfpDtZNuTlV
Bv8KJAV+L8YdcmzUiymMV33a2etmGtNPp99/UsQwxaXJDgLFU793OGgGJMNmyDd+
MB5FcSM1/5DYKp2N57CSTTx/KgqT3M0WRmX3YISLdkuRJ3MUkuDq7o8W6o0OPnYX
v32JgIBEQ+ct4EMJddo26K3biTr1XRKOIwSDAgMBAAGjggEsMIIBKDAPBgNVHRMB
Af8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUJUWBaFAmOD07LSy+
zWrZtj2zZmMwHwYDVR0jBBgwFoAUfAwyH6fZMH/EfWijYqihzqsHWycwOgYIKwYB
BQUHAQEELjAsMCoGCCsGAQUFBzABhh5odHRwOi8vb2NzcC5zdGFyZmllbGR0ZWNo
LmNvbS8wOwYDVR0fBDQwMjAwoC6gLIYqaHR0cDovL2NybC5zdGFyZmllbGR0ZWNo
LmNvbS9zZnJvb3QtZzIuY3JsMEwGA1UdIARFMEMwQQYEVR0gADA5MDcGCCsGAQUF
BwIBFitodHRwczovL2NlcnRzLnN0YXJmaWVsZHRlY2guY29tL3JlcG9zaXRvcnkv
MA0GCSqGSIb3DQEBCwUAA4IBAQBWZcr+8z8KqJOLGMfeQ2kTNCC+Tl94qGuc22pN
QdvBE+zcMQAiXvcAngzgNGU0+bE6TkjIEoGIXFs+CFN69xpk37hQYcxTUUApS8L0
rjpf5MqtJsxOYUPl/VemN3DOQyuwlMOS6eFfqhBJt2nk4NAfZKQrzR9voPiEJBjO
eT2pkb9UGBOJmVQRDVXFJgt5T1ocbvlj2xSApAer+rKluYjdkf5lO6Sjeb6JTeHQ
sPTIFwwKlhR8Cbds4cLYVdQYoKpBaXAko7nv6VrcPuuUSvC33l8Odvr7+2kDRUBQ
7nIMpBKGgc0T0U7EPMpODdIm8QC3tKai4W56gf0wrHofx1l7
-----END CERTIFICATE-----";
static string CaCert = @"-----BEGIN CERTIFICATE-----
MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMx
EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT
HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVs
ZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAw
MFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6
b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVj
aG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZp
Y2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
ggEBAL3twQP89o/8ArFvW59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMg
nLRJdzIpVv257IzdIvpy3Cdhl+72WoTsbhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1
HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNkN3mSwOxGXn/hbVNMYq/N
Hwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7NfZTD4p7dN
dloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0
HZbUJtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO
BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0G
CSqGSIb3DQEBCwUAA4IBAQARWfolTwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjU
sHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx4mcujJUDJi5DnUox9g61DLu3
4jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUwF5okxBDgBPfg
8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K
pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1
mMpYjn0q7pBZc2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0
-----END CERTIFICATE-----";
static void Main(string[] args)
{
//forged, claims to be signed by <intermediate> but the signature is invalid
var leaf = new X509Certificate2(Convert.FromBase64String(LeafPfx));
//valid, signed by CA
var intermediate = new X509Certificate2(Encoding.ASCII.GetBytes(IntermediateCert));
//valid godaddy root CA
var ca = new X509Certificate2(Encoding.ASCII.GetBytes(CaCert));
using var chain = new X509Chain();
chain.ChainPolicy.ExtraStore.Add(intermediate);
chain.ChainPolicy.ExtraStore.Add(ca);
chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllFlags;
chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
chain.ChainPolicy.DisableCertificateDownloads = true;
//true on linux, false on windows
var chainStatus = chain.Build(leaf);
Console.WriteLine($"X509Chain.Build()={chainStatus}, Length: {chain.ChainElements.Count}");
Console.WriteLine("\nchain.ChainElements:");
for (var n = 0; n < chain.ChainElements.Count; n++)
{
var elm = chain.ChainElements[n];
Console.WriteLine($"Element {n}: {elm.Information} {elm.Certificate.GetNameInfo(X509NameType.SimpleName, false)}");
foreach (var st in elm.ChainElementStatus)
Console.WriteLine($"\t[{st.Status}] {st.StatusInformation}");
}
//test server
var intermediateCollection = new X509Certificate2Collection(new[] { intermediate, ca });
var opts = new SslServerAuthenticationOptions
{
ServerCertificateContext = SslStreamCertificateContext.Create(leaf, intermediateCollection, offline: true)
};
async Task ServerFn()
{
var listener = new TcpListener(IPAddress.Loopback, 8077);
listener.Start();
var client = await listener.AcceptTcpClientAsync();
Console.WriteLine($"Client connection from {client.Client.RemoteEndPoint}");
var ssl = new SslStream(client.GetStream());
await ssl.AuthenticateAsServerAsync(opts);
client.Close();
listener.Stop();
};
Console.WriteLine("\nStarting test server on port 8077");
while (true)
{
try { Task.Run(ServerFn).Wait(); }
catch (Exception e) { Console.WriteLine(e); return; }
}
}
}
}
X509Chain.Build()=False, Length: 3
chain.ChainElements:
Element 0: foobar.com
[NotSignatureValid] The signature of the certificate cannot be verified.
Element 1: Starfield Secure Certificate Authority - G2
Element 2: Starfield Root Certificate Authority - G2
Test using
#>openssl s_client -connect localhost:8077
the leaf and the intermediate certificate is received by the client
X509Chain.Build()=True, Length: 1
chain.ChainElements:
Element 0: foobar.com
[PartialChain] unable to get local issuer certificate
Test using
#>openssl s_client -connect localhost:8077
only the leaf certificate is received by the client
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment