I have a PEM encoded certificate. I want to get the ASN.1 BIT STRING of the public key. I am using pyca's cryptography package. All I am getting is the whole subject public key info in DER format. My question is is there any easy way to get only the public key's BIT STRING? Mainly, I want to calculate the issuerKeyHash which is needed to build OCSP request.
Input:
from cryptography import x509
from cryptography.hazmat.primitives.serialization import Encoding, PublicFormat
with open ("test_issuer.pem","rb") as file:
pem_data = file.read()
issuer_cert = x509.load_pem_x509_certificate(pem_data)
pubkey = issuer_cert.public_key()
pubkey_bytes = pubkey.public_bytes(encoding=Encoding.DER, format=PublicFormat.SubjectPublicKeyInfo)
print(pubkey_bytes.hex())
Output:
3059301306072a8648ce3d020106082a8648ce3d030107034200041306605a1910efd18b382f05719062bea9c63a118124bc3cde6a4959734ecef00129c92573255bca278f5a5f3e403128bd9b9ad9d5517c4f796120e673a9aa9e
As mentioned, this is the whole subject public key info (91 bytes). Using an ASN.1 viewer or openssl, I observed that the actual BIT STRING excluding all the algorithm info, tags and length starts from byte 25. I can of course write a function to read all the tags and length info and extract the BIT STRING. But is there any built in function for this purpose?
Expected output:
041306605a1910efd18b382f05719062bea9c63a118124bc3cde6a4959734ecef00129c92573255bca278f5a5f3e403128bd9b9ad9d5517c4f796120e673a9aa9e
The output you expect is the hex encoded public key in uncompressed format. To obtain the uncompressed format, only the encoding and format specification must be changed:
from cryptography.hazmat.primitives.serialization import Encoding, PublicFormat
...
pubkey_bytes = pubkey.public_bytes(encoding=Encoding.X962, format=PublicFormat.UncompressedPoint)
print(pubkey_bytes.hex()) # 041306605a1910efd18b382f05719062bea9c63a118124bc3cde6a4959734ecef00129c92573255bca278f5a5f3e403128bd9b9ad9d5517c4f796120e673a9aa9e