Skip to content

Instantly share code, notes, and snippets.

@yosshy
Created September 14, 2019 10:57
Show Gist options
  • Save yosshy/d90a8d6a536e884af5edeefe612e214d to your computer and use it in GitHub Desktop.
Save yosshy/d90a8d6a536e884af5edeefe612e214d to your computer and use it in GitHub Desktop.
gen_cert: Generate X509 Certificate and Private Key
#!/usr/bin/python
# usage: gen_cert [-h] [-C COUNTRY] [-ST STATE] [-L LOCALITY] [-O ORGANIZATION]
# [-OU ORGANIZATION_UNIT] [-CN COMMON_NAME] [-E EMAIL_ADDRESS]
# [-p PERIOD] [-d DNS] [-i IP] [-s SERIAL]
# certfile keyfile
#
# Generate X509 Certificate and Private Key
#
# positional arguments:
# certfile
# keyfile
#
# optional arguments:
# -h, --help show this help message and exit
# -C COUNTRY, --country COUNTRY
# Country Name (2 letter code)
# -ST STATE, --state STATE
# State or Province Name (full name)
# -L LOCALITY, --locality LOCALITY
# Location; city name
# -O ORGANIZATION, --organization ORGANIZATION
# Organization Name (eg, company)
# -OU ORGANIZATION_UNIT, --organization-unit ORGANIZATION_UNIT
# Organizational Unit Name (eg, section)
# -CN COMMON_NAME, --common-name COMMON_NAME
# Common Name (e.g. server FQDN or YOUR name)
# -E EMAIL_ADDRESS, --email-address EMAIL_ADDRESS
# Email Address
# -p PERIOD, --period PERIOD
# Period to expire in days
# -d DNS, --dns DNS Additional DNS name; multiple usage allowed
# -i IP, --ip IP Additional IP address; multiple usage allowed
# -s SERIAL, --serial SERIAL
# Serial number
import argparse
from OpenSSL import crypto
from socket import gethostname
def main(certfile=None, keyfile=None, country=None, state=None,
locality=None, organization=None, organization_unit=None,
common_name=None, email_address=None, period=None,
dns=None, ip=None, serial=None):
key = crypto.PKey()
key.generate_key(crypto.TYPE_RSA, 2048)
cert = crypto.X509()
subject = cert.get_subject()
if country:
subject.C = country
if state:
subject.ST = state
if locality:
subject.L = locality
if organization:
subject.O = organization # noqa:E741
if organization_unit:
subject.OU = organization_unit
subject.CN = common_name
if email_address:
subject.emailAddress = email_address
cert.set_serial_number(serial)
cert.gmtime_adj_notBefore(0)
cert.gmtime_adj_notAfter(period*24*60*60)
cert.set_issuer(cert.get_subject())
cert.set_pubkey(key)
extensions = [
crypto.X509Extension(
"basicConstraints".encode("ascii"),
False,
"CA:FALSE".encode("ascii")),
]
san = []
if dns:
san += ["DNS:%s" % x for x in dns]
if ip:
san += ["IP:%s" % x for x in ip]
if san:
extensions.append(
crypto.X509Extension(
"subjectAltName".encode("ascii"),
False,
",".join(san).encode("ascii"))
)
cert.add_extensions(extensions)
cert.set_version(2)
cert.sign(key, "sha256")
certfile.write(
crypto.dump_certificate(crypto.FILETYPE_PEM, cert).decode("utf-8"))
certfile.close()
keyfile.write(
crypto.dump_privatekey(crypto.FILETYPE_PEM, key).decode("utf-8"))
keyfile.close()
if __name__ == "__main__":
parser = argparse.ArgumentParser(
description="Generate X509 Certificate and Private Key")
parser.add_argument("certfile", type=argparse.FileType("wx"))
parser.add_argument("keyfile", type=argparse.FileType("wx"))
parser.add_argument("-C", "--country",
help="Country Name (2 letter code)")
parser.add_argument("-ST", "--state",
help="State or Province Name (full name)")
parser.add_argument("-L", "--locality",
help="Location; city name")
parser.add_argument("-O", "--organization",
help="Organization Name (eg, company)")
parser.add_argument("-OU", "--organization-unit",
help="Organizational Unit Name (eg, section)")
parser.add_argument("-CN", "--common-name",
help="Common Name (e.g. server FQDN or YOUR name)",
default=gethostname())
parser.add_argument("-E", "--email-address",
help="Email Address")
parser.add_argument("-p", "--period", type=int,
help="Period to expire in days",
default=365)
parser.add_argument("-d", "--dns", action='append',
help="Additional DNS name; multiple usage allowed")
parser.add_argument("-i", "--ip", action='append',
help="Additional IP address; multiple usage allowed")
parser.add_argument("-s", "--serial", type=int,
help="Serial number",
default=1000)
args = parser.parse_args()
main(**args.__dict__)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment