Skip to content

Instantly share code, notes, and snippets.

@amcginlay
Last active August 9, 2023 13:46
Show Gist options
  • Save amcginlay/220cc220c1ebcd1d38d93db7239c9068 to your computer and use it in GitHub Desktop.
Save amcginlay/220cc220c1ebcd1d38d93db7239c9068 to your computer and use it in GitHub Desktop.
Commands to prepare Digicert key material for ACM import

Preparing TLSPC PEM files for AWS ACM

Assuming we have cert-chain and private key files extracted from TLSPC via DigiCert (let's call them my-cert.chain and my-cert.key), how do we get them prepared for AWS ACM import.

In this case my-cert.chain is a full chain and my-cert.key is an encrypted private key.

Requirements

As such we need to cope with two requirements:

  • Extract the leaf-level cert from the cert chain
  • Decrypt the private key

We'll show these steps separately before showing how they can be combined to complete the import.

Extract the leaf-level cert from the cert chain

The ACM import feature requires the PEM text to include only the leaf-level certificate.

For clarity, the format of a full chain is as follows.

-----BEGIN CERTIFICATE-----
<LEAF>
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
<INTERMEDIATE>
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
<ROOT>
-----END CERTIFICATE-----

IMO the easiest way to extract just the leaf certificate from the full chain is as follows:

openssl x509 -in my-cert.chain

... this is much simpler than the examples you'll find online!

Decrypt the private key

Certificates extracted from TLSPC via DigiCert will be accompanied by an encrypted private key which starts with the following PEM header:

-----BEGIN ENCRYPTED PRIVATE KEY-----

The ACM import feature requires the PEM text to be unencrypted. Encrypted private key files can be decrypted as follows:

password=<PRIVATE_KEY_PASSWORD>
openssl rsa -in my-cert.key -passin pass:${password}

AWS ACM import

We bring all this together to complete the ACM import:

aws acm import-certificate \
  --certificate-chain fileb://my-cert.chain \
  --certificate fileb://<(openssl x509 -in my-cert.chain) \
  --private-key fileb://<(openssl rsa -in my-cert.key -passin pass:${password})

Appendix (Python)

Code to perform the same operations in Python as follows

from cryptography import x509
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization

def read_file(path):
    try:
        with open(path, "rb") as file:
            file_content = file.read()
            return file_content
    except FileNotFoundError:
        print(f"File '{path}' not found.")
    except Exception as e:
        print("An error occurred:", e)
        return None

def chain_to_leaf(chain_content):
    cert = x509.load_pem_x509_certificate(chain_content, default_backend())
    cert_text = cert.public_bytes(serialization.Encoding.PEM).decode('utf-8')
    return cert_text

def decrypt_private_key(encrypted_key_content, password):
    key = serialization.load_pem_private_key(
        encrypted_key_content,
        password=password,
        backend=default_backend()
    )
    key_pem = key.private_bytes(
        encoding=serialization.Encoding.PEM,
        format=serialization.PrivateFormat.PKCS8,
        encryption_algorithm=serialization.NoEncryption()
    )
    key_text = key_pem.decode('utf-8')
    return key_text

# EXTRACT LEAF CERT FROM CHAIN
chain_file = "my-cert.chain"
chain_content = read_file(chain_file)
print(chain_to_leaf(chain_content))

# DECRYPT ENCRYPTED PRIVATE KEY
password=b"<PASSWORD>"
encrypted_key_file = "my-cert.key"
encrypted_key_content = read_file(encrypted_key_file)
print(decrypt_private_key(encrypted_key_content, password))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment