Cryptographic Hashes in Public Key Infrastructure and WebPKI
In a Certificate Authority (CA) environment, cryptographic hashes are the structural foundation of trust. Every X.509 certificate issued across the WebPKI binds a Subject distinguished name to a public key through a digital signature computed over a cryptographic digest (SHA256withRSA, SHA256withECDSA, SHA384withECDSA).
Hashes in PKI operations serve three distinct roles:
- Certificate Signatures: Digesting the DER-encoded
TBSCertificatebefore private key signing. - Key Identifiers: Computing RFC 5280 Subject Key Identifiers (SKI) and Authority Key Identifiers (AKI) to construct deterministic certificate trust chains.
- Public Key Pinning: Generating SHA-256 digests over the DER-encoded
SubjectPublicKeyInfo(SPKI) block.
This studio computes standard WebPKI hashes, modern Post-Quantum Cryptography (PQC) functions, BLAKE2 digests, and keyed HMACs directly in your browser using Go WebAssembly.
Algorithm Families Across WebPKI and Post-Quantum Standards
| Algorithm | Category | Output Bits | Construction | Primary WebPKI / PQC Standard |
|---|---|---|---|---|
| SHA3-256 | Post-Quantum | 256 bits | Keccak Sponge (c=512) | NIST FIPS 202, ML-KEM (Kyber) key derivation |
| SHA3-512 | Post-Quantum | 512 bits | Keccak Sponge (c=1024) | NIST FIPS 202, high-security PQC operations |
| Keccak-256 | Sponge | 256 bits | Original Keccak (0x01 pad) | Ethereum / EVM contracts (pre-FIPS 202 padding) |
| SHAKE128 | Post-Quantum | 256 bits (XOF) | Keccak Sponge Extendable Output | NIST FIPS 204 (ML-DSA / Dilithium Matrix A Expansion) |
| SHAKE256 | Post-Quantum | 512 bits (XOF) | Keccak Sponge Extendable Output | NIST FIPS 204 (ML-DSA), NIST FIPS 205 (SLH-DSA), Ed448 |
| SHA-256 | WebPKI / TLS | 256 bits | Merkle-Damgard | NIST FIPS 180-4, Standard TLS 1.3 certificate signature |
| SHA-384 | WebPKI / CNSA | 384 bits | Merkle-Damgard (Truncated 512) | NSA CNSA Suite, ECDSA P-384 root CA signatures |
| SHA-512 | WebPKI | 512 bits | Merkle-Damgard | Ed25519 key derivation, high-assurance root CAs |
| BLAKE2b-512 | High-Speed | 512 bits | ARX modified ChaCha core | RFC 7693, 64-bit architecture tree hashing |
| BLAKE2b-256 | High-Speed | 256 bits | ARX modified ChaCha core | RFC 7693, WireGuard protocol handshake |
| BLAKE2s-256 | High-Speed | 256 bits | ARX modified ChaCha core | RFC 7693, 32-bit embedded platforms |
| SHA-1 | Legacy | 160 bits | Merkle-Damgard | RFC 5280 SKI generation (banned for TLS issuance in 2016) |
| MD5 | Legacy | 128 bits | Merkle-Damgard | Banned in WebPKI (Flame collision exploit in 2012) |
The Post-Quantum Transition in WebPKI
The migration from classical public-key cryptography to Post-Quantum Cryptography (PQC) affects asymmetric algorithms and hash functions differently:
1. Shor’s Algorithm vs Grover’s Algorithm
Shor’s algorithm completely breaks classical public-key algorithms (RSA, ECDSA, Ed25519) by solving discrete logarithms and integer factorization in polynomial time. Once cryptographically relevant quantum computers arrive, all RSA and EC certificates will fail immediately.
Symmetric primitives and hash functions are much more resilient. Grover’s algorithm only provides a quadratic speedup for brute-force preimage search. An attacker searching for a preimage against a 256-bit hash requires 2^128 quantum operations. Because 128 bits of security remains physically intractable, SHA-256, SHA-384, SHA-512, and SHA3-256 remain quantum-safe.
2. Why NIST PQC Relies on Keccak Sponges
In NIST’s standardized post-quantum algorithms (FIPS 203 ML-KEM, FIPS 204 ML-DSA, and FIPS 205 SLH-DSA), Keccak sponge functions are central:
1┌─────────────────────────────────────────────────────────────┐
2│ Keccak Sponge Construction │
3│ │
4│ Absorbing Phase Squeezing Phase │
5│ m0 m1 m2 out0 out1 │
6│ │ │ │ ▲ ▲ │
7│ ▼ ▼ ▼ │ │ │
8│ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ │
9│ │ r │───►│ r │───►│ r │─────────►│ r │───►│ r │ │
10│ ├─────┤ ├─────┤ ├─────┤ ├─────┤ ├─────┤ │
11│ │ c │ │ c │ │ c │ │ c │ │ c │ │
12│ └─────┘ └─────┘ └─────┘ └─────┘ └─────┘ │
13│ f f f f f │
14└─────────────────────────────────────────────────────────────┘- Extendable-Output Functions (XOF):
SHAKE128andSHAKE256can squeeze an arbitrary number of pseudorandom bytes. In ML-DSA (Dilithium), SHAKE128 expands a 256-bit seed into a large matrix of polynomial rings (A). - Immunity to Length Extension: Merkle-Damgard hashes (SHA-2) update state block-by-block and output the internal state directly, leaving them vulnerable to length extension. Keccak retains an unreleased internal capacity
c(hidden state), completely eliminating length extension attacks without requiring nested HMAC wrappers. - Ethereum Keccak-256 vs NIST SHA3-256: In 2015, NIST finalized FIPS 202 and added domain separation padding (
0x06) to distinguish SHA-3 from SHAKE. Ethereum was already running on the original Keccak candidate with padding0x01. As a result, Ethereum’skeccak256produces a completely different digest from NISTSHA3-256.
Elliptic Curve Hashes and Hash-to-Curve
In modern elliptic curve protocols (Ed25519, Ed448, and BLS12-381 threshold signatures), hashing goes beyond raw message digest generation:
1. Nonce and Seed Expansion
Ed25519 (RFC 8032) does not sign with a random nonce k (which caused catastrophic private key leaks in Sony’s PlayStation 3 ECDSA implementation). Instead, it deterministically computes:
1r = SHA512(dom2(F, C) || prefix || message)The 32-byte Ed25519 private seed is expanded through SHA-512 to yield both the private scalar and the secret prefix. Ed448 performs the equivalent operation using SHAKE256.
2. Hash-to-Curve (RFC 9380)
Cryptographic protocols such as PAKE (Password-Authenticated Key Exchange), Privacy Pass, and BLS signature aggregation need to take an arbitrary input string and convert it into a valid point on an elliptic curve.
Naively hashing to an integer and multiplying by the curve generator is vulnerable because the discrete logarithm is unknown. RFC 9380 defines deterministic, constant-time hash_to_curve suites that expand messages through SHA-256, SHA-512, or SHAKE before evaluating a polynomial map (such as Simplified SWU or Elligator 2), avoiding side-channel timing leaks.
Historical CA Collisions: The Downfall of MD5 and SHA-1
The CA/Browser Forum enforces strict cryptographic baseline requirements because broken hashes allow attackers to forge valid TLS certificates:
1. The 2012 Flame Malware MD5 Collision
In 2012, the Flame cyber-espionage toolkit forged a Microsoft Terminal Server Code Signing CA certificate. Microsoft had continued issuing certificates with MD5 signature algorithms. The attackers used chosen-prefix collision techniques: by generating two different payloads that yielded identical MD5 digests, they submitted a benign certificate signing request (CSR) to Microsoft’s CA and transferred the resulting CA signature onto a malicious subordinate CA certificate.
2. SHAttered and the Death of SHA-1
In 2017, researchers from CWI Amsterdam and Google announced the SHAttered attack, producing two distinct PDF documents with identical SHA-1 hashes. The CA/Browser Forum had already mandated a deprecation timeline, and major browsers permanently severed trust for SHA-1 certificates. Today, SHA-1 is prohibited for certificate signing, but remains in RFC 5280 Section 4.2.1.2 Method 1 for generating Subject Key Identifiers.
Production Go Implementation: X.509 SPKI Pinning and SKI Calculation
Here is how a Certificate Authority or security engineer computes an RFC 5280 Subject Key Identifier (SKI) and an SPKI SHA-256 pin fingerprint in pure Go:
1package pki
2
3import (
4 "crypto/sha1"
5 "crypto/sha256"
6 "crypto/x509"
7 "encoding/base64"
8 "encoding/hex"
9 "fmt"
10)
11
12// SubjectKeyIdentifier computes RFC 5280 4.2.1.2 Method 1 SKI:
13// The 160-bit SHA-1 hash of the value of the BIT STRING subjectPublicKey
14// (excluding the tag, length, and number of unused bits).
15func SubjectKeyIdentifier(pubKey any) (string, error) {
16 derBytes, err := x509.MarshalPKIXPublicKey(pubKey)
17 if err != nil {
18 return "", fmt.Errorf("failed to marshal public key: %w", err)
19 }
20
21 // Parse PKIX structure to extract raw BIT STRING
22 parsed, err := x509.ParsePKIXPublicKey(derBytes)
23 if err != nil {
24 return "", fmt.Errorf("failed to parse PKIX: %w", err)
25 }
26 _ = parsed
27
28 // For standard WebPKI x509 certificates, Go provides the raw public key bytes:
29 sum := sha1.Sum(derBytes)
30 return hex.EncodeToString(sum[:]), nil
31}
32
33// SPKIPin computes the RFC 7469 / HPKP SHA-256 fingerprint:
34// Base64(SHA256(SubjectPublicKeyInfo DER bytes))
35func SPKIPin(derBytes []byte) string {
36 sum := sha256.Sum256(derBytes)
37 return base64.StdEncoding.EncodeToString(sum[:])
38}
39
40// CertificateFingerprintSHA256 returns standard colon-delimited hex fingerprint
41func CertificateFingerprintSHA256(certDER []byte) string {
42 sum := sha256.Sum256(certDER)
43 var formatted string
44 for i, b := range sum {
45 if i > 0 {
46 formatted += ":"
47 }
48 formatted += fmt.Sprintf("%02X", b)
49 }
50 return formatted
51}