Created
September 7, 2020 18:53
-
-
Save Arbitrage0/de4e0defb20bc539d6db27e4334e0e67 to your computer and use it in GitHub Desktop.
Create an x509 certificate for a key hosted on Google HSM
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
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