Security /info/alibaba/ssl

Let's Encrypt Part 2

Date Created: June 12, 2018
Last Update: June 21, 2018

Table of Contents

Introduction
Account Key
Certificate Key
Certificate Signing Request

Article Series

NeoPrime - Let's Encrypt Part 1
NeoPrime - Let's Encrypt Part 2
NeoPrime - Let's Encrypt Part 3
NeoPrime - Let's Encrypt Part 4
NeoPrime - Let's Encrypt Part 5

Introduction

In this multipart article, we will learn how to use the Let's Encrypt ACME version 2 API using Python to develop software that can create, install, renew and revoke SSL certificates for Alibaba Cloud. The same principles apply to any computing service that supports X.509 SSL certificates.

In this part we will explain how to create your Account Key, Certificate Key and Certificate Signing Request (CSR).

The following source code examples do not have error checking. These code snips are designed to demonstrate how to interface with ACME. For more complete examples, review the source code in the examples package that you can download: ACME Examples.

Account Key

The Account Key is used to provide the identity of the account that is requesting certificate services. There is no login / password or similar method used. Therefore, it is very important to save your Account Key keypair in a safe location as the Account Key is used to issue, renew and revoke SSL certificates. If you lose the Account Key the certificates that were created under that account will be in limbo. You will not be able to renew or revoke those certificates. In this case you will need to create a new Account Key and issue new SSL certificates to replace the once that you lost control of. If a malicious third party obtained access to your Account Key, they could change the contact email address and revoke your certificates. They would not be able to issue new SSL certificates for your domains as this would require either HTTP or DNS validation of the domain names.

I could not find documentation on the size of the private key. I have been testing with a key size of 4096 bits and this works just fine.

There are numerous methods to create the Account Key. Let's look at two methods: writing a Python program and using OpenSSL from the command line. Included are examples showing how to work with private keys.

This example does not use the openssl python libraries. This example uses the crypto libraries which makes creating a private key very simple. Following this example is one using openssl which is more complicated but has more options.

make_account_key.py

""" Let's Encrypt ACME Version 2 Examples - Create Account Key """

from Crypto.PublicKey import RSA

filename = 'account.key'

key = RSA.generate(4096)

with open(filename,'w') as f:
	f.write(key.exportKey().decode('utf-8'))

make_account_key2.py

import sys
import OpenSSL
from OpenSSL import crypto

filename = 'account.key'

key = crypto.PKey()

key.generate_key(crypto.TYPE_RSA, 4096)

key_material = crypto.dump_privatekey(crypto.FILETYPE_PEM, key)

val = key_material.decode('utf-8')

with open("account.key", "wt") as f:
	f.write(val)


OpenSSL Command Line Example:

openssl genrsa -out account.key 4096

OpenSSL command line options:

  • genrsa - generate an RSA private key (PKCS#1 format)
  • -out filename - output the key to the specified file
  • 4096 - the size of the private key to generate in bits


View details and verify the new account key:

openssl rsa -in account.key -text -check -noout

Extract the public key from the private key:

openssl rsa -pubout -in account.key -out account.pub

Certificate Key:

The Certificate Key is a keypair used to sign CSRs (Certificate Signing Request). This is not the Account Key even though both are keypairs. For security reasons you do not want to use the Account Key to sign CSRs. Common practice is to create a new Certificate Key for each SSL Certificate.

We will repeat the above examples to create the certificate key. The difference is that the filename will be the name of our domain name that we will be issuing the certificate for. Change "domain.com" to your domain name.

make_certificate_key.py

""" Let's Encrypt ACME Version 2 Examples - Create Certificate Key """

from Crypto.PublicKey import RSA

domainname = "example.com"

filename = domainname + '.key'

key = RSA.generate(4096)

with open(filename,'w') as f:
	f.write(key.exportKey().decode('utf-8'))

OpenSSL Command Line Example:

openssl genrsa -out example.com.key 4096

OpenSSL command line options:

  • genrsa - generate an RSA private key (PKCS#1 format)
  • -out filename - output the key to the specified file
  • 4096 - the size of the private key to generate in bits

CSR - Certificate Signing Request:

A CSR is a file (message) sent to a CA (Certificate Authority - Let's Encrypt) to apply for an SSL certificate. The CSR contains details about who is applying for the SSL certificate such as company name, location, domain name, etc. Since Let's Encrypt only issues DV (Domain Validated) SSL certificates, only the domain names are validated and only the domain names are included in the generated SSL certificate plus an optional email address for contact information. Details such as company name, location, etc. are not included.

Generating a CSR is easy with OpenSSL. All that is required is the domain name and optionally an email address. In the following example, replace domainName with your domain name and emailAddress with your email address.

This example also removes all the subject fields that Let's Encrypt does not process such as C, ST, L, O and OU and does add the subjectAltName extension that Chrome requires.

make_csr.py

""" Let's Encrypt ACME Version 2 Examples - Create CSR (Certificate Signing Request) """

importOpenSSL

KEY_FILE = "certificate.key"
CSR_FILE = "certificate.csr"

domainName = 'api.neoprime.xyz'
emailAddress = 'support@neoprime.xyz'

def create_csr(pkey, domain_name, email_address):
	""" Generate a certificate signing request """

	# create certificate request
	cert = OpenSSL.crypto.X509Req()

	# Add the email address
	cert.get_subject().emailAddress = email_address

	# Add the domain name
	cert.get_subject().CN = domain_name

        san_list = ["DNS:" + domain_name]

        cert.add_extensions([
                OpenSSL.crypto.X509Extension(
			b"subjectAltName",
			False,
			", ".join(san_list).encode("utf-8"))
        ])

	cert.set_pubkey(pkey)
	cert.sign(pkey, 'sha256')

	return cert

# Load the Certicate Key
data = open(KEY_FILE, 'rt').read()

# Load the private key from the certificate.key file
pkey = OpenSSL.crypto.load_privatekey(OpenSSL.crypto.FILETYPE_PEM, data)

# Create the CSR
cert = create_csr(pkey, domainName, emailAddress)

# Write the CSR to a file in PEM format
with open(CSR_FILE,'wt') as f:
	data = OpenSSL.crypto.dump_certificate_request(OpenSSL.crypto.FILETYPE_PEM, cert)
	f.write(data.decode('utf-8'))


In Part 3 we will begin going through each Let's Encrypt ACME API using the account.key, certificate.key and certificate.csr files to generate and install SSL certificates for Alibaba Cloud API Gateway and CDN.

Let's Encrypt Part 3.




15220 Main Street, Bellevue, WA 98007
T: 425-528-8500 - F: 425-528-8550 - E: neoprime@neoprime.io

Copyright 2018 NeoPrime LLC