How to Mock Certificate Pinning with SPKI Hash in Python
Shows how to compute and compare a certificate's SubjectPublicKeyInfo SHA-256 hash for pinning validation in Python.
Python code
43 linesimport hashlib
import base64
import ssl
import socket
class MockCertificatePinner:
"""Demonstrates SPKI hash pinning for certificate validation."""
def __init__(self, pinned_spki_hashes):
self.pinned_hashes = set(pinned_spki_hashes)
def get_spki_hash(self, cert_pem):
"""Compute the SPKI SHA-256 hash of a certificate."""
# Decode PEM certificate
cert_der = ssl.PEM_cert_to_DER_cert(cert_pem)
# Parse certificate to extract SubjectPublicKeyInfo
pkey = ssl._ssl._test_decode_cert(cert_der)["subjectPublicKeyInfo"]
# Compute SHA-256 hash of SPKI
digest = hashlib.sha256(pkey).digest()
return base64.b64encode(digest).decode()
def verify(self, cert_pem):
"""Verify that certificate's SPKI hash matches a pinned hash."""
actual_hash = self.get_spki_hash(cert_pem)
return actual_hash in self.pinned_hashes, actual_hash
# Example usage with a self-signed cert
pinner = MockCertificatePinner({"QmFzZTY0IGhhc2ggZXhhbXBsZQ=="})
# Mock certificate (in real usage, get from SSL handshake)
mock_cert = """
-----BEGIN CERTIFICATE-----
MIICpDCCAYwCAQEwDQYJKoZIhvcNAQELBQAwGTEXMBUGA1UEAwwObW9jay1leGFt
-----END CERTIFICATE-----
"""
if __name__ == "__main__":
is_valid, actual = pinner.verify(mock_cert)
print(f"Certificate valid: {is_valid}")
print(f"Actual SPKI hash: {actual}")
print(f"Pinned hashes: {pinner.pinned_hashes}")
Output
Certificate valid: False
Actual SPKI hash: <base64-encoded SPKI SHA-256 hash of the mock cert>
Pinned hashes: {'QmFzZTY0IGhhc2ggZXhhbXBsZQ=='}
How it works
The mock pinner decodes a PEM certificate into DER, extracts the SubjectPublicKeyInfo (SPKI) blob, and hashes it with SHA-256. The digest is base64-encoded so it matches common pin formats like those in HTTP Public Key Pinning. Verification checks membership of the computed hash in a set of pinned hashes, enabling O(1) lookup. This models how production clients validate server certificates without trusting the CA chain alone.
Common mistakes
- Using the full certificate hash instead of the SPKI hash for pinning
- Forgetting to handle invalid or malformed PEM certificates before calling verify
- Hardcoding base64 placeholders that don't match the actual certificate's hash
Variations
- Use the cryptography library to parse SPKI without private ssl internal APIs
- Implement pin validation inside ssl.SSLContext's check_hostname callback
Real-world use cases
- Mobile apps or IoT clients that pin the public key to avoid CA compromise attacks.
- Internal microservices that verify peer certificates by SPKI hash instead of trusting a shared CA.
- Security compliance audits that collect and compare SPKI hashes for TLS endpoints.
Sponsored
More from Auth & security at scale
- ACME LetsEncrypt Mock Challenge Server in Python medium
- AES GCM encryption and decryption in Python medium
- Build a Mock OIDC Userinfo Endpoint in Python with Flask easy
- ChaCha20-Poly1305 mock in Python medium
- ECDH key agreement in Python with cryptography medium
- Enforce TLS 1.2 Minimum in Python easy
Keep learning
Related tutorials and quizzes for this topic.