Search code examples
c#.netsslpkcs#8pkcs#1

Get certificate's public key in the PKCS8 format


Environment:

Windows 11 24H2

.Net Framework 4.8, 4.7.2

Problem:

I do not understand how to get server's certificate public key in PKCS8 format using the X509Certificate class.

Explanation:

I'm implementing the custom server's certificate check for SSL connection (aka certificate pinning) in the next way:

  • Create a new SSLStream:
SslStream sslStream = new SslStream(
    client.GetStream(),
    false,
    new RemoteCertificateValidationCallback(ValidateServerCertificate),
    null);
  • Declare the ValidateServerCertificate() method:
    public static bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) {}
  • Get server's certificate public key
    certificate.GetPublicKey()

The public key which I get is in the PKCS1 format and I can't find any function in .Net Framework to get it in the PKCS8 format or to convert from PCKS1 to PKCS8. As a fallback, I'm using the static prefix for the PKCS8 format which works well but is valid only for 2048 bits long public keys:

private static byte[] pkcs8Prefix = { 0x30, 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00 };
byte[] pkcs8PublicKey = pkcs8Prefix.Concat(certificate.GetPublicKey()).ToArray();

Which function of .Net Framework can I use to get the public key in the PKCS8 format?


Solution

  • In the end I achieved the needed result using the Bouncy Castle library for c# because .Net Framework does not have an easy way to do it. https://github.com/bcgit/bc-csharp/discussions/592