Commit 5eefadd6 authored by bitkeeper's avatar bitkeeper Committed by oroulet

Add several helpers for creating certificates for the following tasks:

* create private keys
* create self signed certficates
* create certifcate signing requests
* create ca for signing csr

The helpers are:
* generate_private_key
* generate_app_certificate_signing_request
* generate_self_signed_app_certificate
* sign_certificate_request

Test and example are available.
parent 69ad65c6
This diff is collapsed.
......@@ -8,7 +8,7 @@ from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives import hmac
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives.asymmetric import padding, rsa
from cryptography.hazmat.primitives.ciphers import Cipher
from cryptography.hazmat.primitives.ciphers import algorithms
from cryptography.hazmat.primitives.ciphers import modes
......@@ -85,6 +85,16 @@ def der_from_x509(certificate):
return b""
return certificate.public_bytes(serialization.Encoding.DER)
def pem_from_key(private_key: rsa.RSAPrivateKey) -> bytes:
"""dumps a private key in PEM format
Args:
private_key (rsa.RSAPrivateKey): The privatekey to dump
Returns:
bytes: The private as PEM/PKCS8 format
"""
return private_key.private_bytes(encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.PKCS8, encryption_algorithm=serialization.NoEncryption())
def sign_sha1(private_key, data):
return private_key.sign(
......
""" Example of several certficate creation helpers"""
import asyncio
from pathlib import Path
import socket
from cryptography import x509
from cryptography.hazmat.primitives.serialization import Encoding # , load_pem_private_key
from cryptography.x509.oid import ExtendedKeyUsageOID
from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey
from asyncua.crypto.uacrypto import load_certificate, load_private_key
from asyncua.crypto.cert_gen import generate_private_key, generate_self_signed_app_certificate, dump_private_key_as_pem, generate_app_certificate_signing_request, sign_certificate_request
HOSTNAME: str = socket.gethostname()
# used for subject common part
NAMES: dict[str, str] = {
'countryName': 'NL',
'stateOrProvinceName': 'ZH',
'localityName': 'Foo',
'organizationName': "Bar Ltd",
}
CLIENT_SERVER_USE = [ExtendedKeyUsageOID.CLIENT_AUTH, ExtendedKeyUsageOID.SERVER_AUTH]
# setup the paths for the certs, keys and csr
base = Path('certs-example')
base_csr: Path = base / 'csr'
base_private: Path = base / 'private'
base_certs: Path = base / 'certs'
base_csr.mkdir(parents=True, exist_ok=True)
base_private.mkdir(parents=True, exist_ok=True)
base_certs.mkdir(parents=True, exist_ok=True)
def generate_private_key_for_myserver():
key: RSAPrivateKey = generate_private_key()
key_file = base_private / "myserver.pem"
key_file.write_bytes(dump_private_key_as_pem(key))
async def generate_self_signed_certificate():
subject_alt_names: list[x509.GeneralName] = [x509.UniformResourceIdentifier(f"urn:{HOSTNAME}:foobar:myselfsignedserver"),
x509.DNSName(f"{HOSTNAME}")]
# key: RSAPrivateKey = generate_private_key()
key = await load_private_key(base_private / "myserver.pem")
cert: x509.Certificate = generate_self_signed_app_certificate(key,
f"myselfsignedserver@{HOSTNAME}",
NAMES,
subject_alt_names,
extended=CLIENT_SERVER_USE)
cert_file = base_certs / "myserver-selfsigned.der"
cert_file.write_bytes(cert.public_bytes(encoding=Encoding.DER))
def generate_applicationgroup_ca():
subject_alt_names: list[x509.GeneralName] = [x509.UniformResourceIdentifier(f"urn:{HOSTNAME}:foobar:myserver"),
x509.DNSName(f"{HOSTNAME}")]
key: RSAPrivateKey = generate_private_key()
cert: x509.Certificate = generate_self_signed_app_certificate(key,
"Application CA",
NAMES,
subject_alt_names,
extended=[])
key_file = base_private / 'ca_application.pem'
cert_file = base_certs / 'ca_application.der'
key_file.write_bytes(dump_private_key_as_pem(key))
cert_file.write_bytes(cert.public_bytes(encoding=Encoding.DER))
async def generate_csr():
subject_alt_names: list[x509.GeneralName] = [x509.UniformResourceIdentifier(f"urn:{HOSTNAME}:foobar:myserver"),
x509.DNSName(f"{HOSTNAME}")]
key: RSAPrivateKey = generate_private_key()
key = await load_private_key(base_private / 'myserver.pem')
csr: x509.CertificateSigningRequest = generate_app_certificate_signing_request(key,
f"myserver@{HOSTNAME}",
NAMES,
subject_alt_names,
extended=CLIENT_SERVER_USE)
# key_file = base_private / 'myserver.pem'
csr_file = base_csr / 'myserver.csr'
# key_file.write_bytes(dump_private_key_as_pem(key))
csr_file.write_bytes(csr.public_bytes(encoding=Encoding.PEM))
async def sign_csr():
# setup some common data (normally this differs for the CA and the CSR)
subject_alt_names: list[x509.GeneralName] = [x509.UniformResourceIdentifier(f"urn:{HOSTNAME}:foobar:myserver"),
x509.DNSName(f"{HOSTNAME}")]
issuer = await load_certificate(base_certs / 'ca_application.der')
key_ca = await load_private_key(base_private / 'ca_application.pem')
csr_file: Path = base_csr / 'myserver.csr'
csr = x509.load_pem_x509_csr(csr_file.read_bytes())
cert: x509.Certificate = sign_certificate_request(csr, issuer, key_ca, days=30)
(base_certs / 'myserver.der').write_bytes(cert.public_bytes(encoding=Encoding.DER))
async def main():
# create key and reuse it for self_signed and generate_csr
generate_private_key_for_myserver()
# generate self signed certificate for myserver-selfsigned
await generate_self_signed_certificate()
# generate certificate signing request and sign it with the ca for myserver
generate_applicationgroup_ca()
await generate_csr()
await sign_csr()
if __name__ == "__main__":
try:
asyncio.run(main())
except Exception as exp:
print(exp)
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment