using System.Security.Cryptography; using var key = ECDsa.Create();key.ImportFromPem(File.ReadAllText("pub.pem")); // parsing first: a non-key fails here byte[] spki = key.ExportSubjectPublicKeyInfo(); // canonical SPKI DERbyte[] digest = SHA256.HashData(spki); Console.WriteLine(string.Join(":", digest.Select(b => b.ToString("x2")))); // OpenSSL's dgst -c layoutConsole.WriteLine(Convert.ToBase64String(digest)); // pin-sha256 (RFC 7469) using System.Security.Cryptography.X509Certificates; // The key inside a certificate — not cert.GetCertHash(), which hashes the whole certificateusing X509Certificate2 cert = X509CertificateLoader.LoadCertificateFromFile("cert.pem");byte[] keyDigest = SHA256.HashData(cert.PublicKey.ExportSubjectPublicKeyInfo());Console.WriteLine($"certificate key: {Convert.ToHexStringLower(keyDigest)}");Console.WriteLine($"certificate itself: {cert.GetCertHashString(HashAlgorithmName.SHA256)}"); How it works
ImportFromPemparses the key first, so a damaged file or a certificate passed by mistake throws instead of yielding a fingerprint of the wrong bytes.ExportSubjectPublicKeyInfo()re-encodes the key as SPKI DER — the same 91 bytes for a P-256 key whether it came from PEM, a certificate orECDsa.Create.SHA256.HashDatais the one-shot hash API (.NET 5+); the hex with colons matchesopenssl dgst -sha256 -c, the base64 form is thepin-sha256used by HTTP public key pinning.- For a certificate,
cert.PublicKey.ExportSubjectPublicKeyInfo()gives the key's SPKI without choosing between ECDSA and RSA accessors.
Gotchas
cert.GetCertHash()andcert.Thumbprinthash the whole certificate — andThumbprintuses SHA-1. Neither equals the key fingerprint, and both change when the certificate is renewed with the same key.- Hashing
File.ReadAllBytes("pub.pem")hashes PEM text, including line endings. Only the DER is canonical across tools. Convert.ToHexStringreturns uppercase andConvert.ToHexStringLower(.NET 9+) lowercase. Normalize case before comparing fingerprints from different tools.- OpenSSH fingerprints (
SHA256:…) hash the SSH encoding of the key and never match the SPKI fingerprint of the same key.