Skip to content

Instantly share code, notes, and snippets.

@Arbitrage0
Created September 7, 2020 18:53
Show Gist options
  • Save Arbitrage0/de4e0defb20bc539d6db27e4334e0e67 to your computer and use it in GitHub Desktop.
Save Arbitrage0/de4e0defb20bc539d6db27e4334e0e67 to your computer and use it in GitHub Desktop.
Create an x509 certificate for a key hosted on Google HSM
"""
Here's how to create an x509 public key certificate
for your private key hosted on Google HSM in python.
Assumes 2048-bit RSA with PKCS#1 v1.5 Padding
"""
from google.cloud import kms
from asn1crypto import x509
from cryptography import x509 as cx
from oscrypto import asymmetric
import datetime
from asn1crypto.util import timezone
import base64
import hashlib
from certbuilder import pem_armor_certificate
client = kms.KeyManagementServiceClient()
project_id = "INSERT PROJECT ID HERE"
location = "INSERT LOCATION"
key_ring_id = "INSERT KEY RING ID HERE"
key_id = "INSERT KEY ID HERE"
version_id = "INSERT VERSION ID HERE"
# Build the key version name.
key_version_name = client.crypto_key_version_path(project_id, location, key_ring_id, key_id, version_id)
# Call the API to get the Public Key PEM
public_key = client.get_public_key(request={'name': key_version_name})
pkey = bytes(public_key.pem, 'utf-8')
def create_x509TBS_certificate(public_key):
pubkey = asymmetric.load_public_key(public_key)
one_day = datetime.timedelta(1, 0, 0)
self_dict = {
'country_name': 'England',
'state_or_province_name': 'Greater London',
'locality_name': 'London',
'organization_name': 'GoogleHSM CA',
'common_name': 'GoogleHSM CA',
}
tbs_cert = x509.TbsCertificate({
'version': 'v3',
'serial_number': cx.random_serial_number(),
'signature': {
'algorithm': 'sha256_rsa'
},
'issuer': x509.Name.build(self_dict),
'validity': {
'not_before': x509.Time(name='utc_time', value=datetime.datetime.now(timezone.utc) - one_day),
'not_after': x509.Time(name='utc_time', value=datetime.datetime.now(timezone.utc) + (one_day * 365)),
},
'subject': x509.Name.build(self_dict),
'subject_public_key_info': pubkey.asn1,
'extensions': []
})
return tbs_cert
def sign_asymmetric(key_version_name, message_bytes):
# Calculate the hash.
hash_ = hashlib.sha256(message_bytes).digest()
# Build the digest.
digest = {'sha256': hash_}
# Call the API
sign_response = client.asymmetric_sign(request={'name': key_version_name, 'digest': digest})
return sign_response.signature
def get_cert_pem(tbs_cert, signature):
cert = x509.Certificate({
'tbs_certificate': tbs_cert,
'signature_algorithm': {
'algorithm': 'sha256_rsa'
},
'signature_value': signature
})
return pem_armor_certificate(cert)
tbs = create_x509TBS_certificate(pkey)
sig = sign_asymmetric(key_version_name, tbs.dump())
HSM_cert = get_cert_pem(tbs, sig)
print(HSM_cert)
filename = "new.crt.pem"
with open(filename, 'wb') as f:
f.write(HSM_cert)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment