代码
import os
import datetime
from cryptography import x509
from cryptography.x509 import CertificateBuilder
from cryptography.x509.oid import NameOID
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization, hashes
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives.serialization import Encoding
def generate_ssl(
C: str = 'CN', ST: str = 'Shanghai', L: str = 'Shanghai', O: str = '', OU: str = '',
CN: str = '', SANS=None, days: int = 730
):
"""
默认使用RSA2048
:param C: 国家
:param ST: 省份
:param L: 城市
:param O: 组织
:param OU: 组织单位
:param CN: 通用名
:param SANS: 备用名
:param days: 有效期(天),从当日开始计算
:return: crt, key
"""
if SANS is None:
SANS = []
root_crt = os.path.join(os.getcwd(), "cer/root/root.crt")
root_key = os.path.join(os.getcwd(), "cer/root/root.key.pem")
# 使用CA证书签发新证书
csr = x509.CertificateSigningRequestBuilder().subject_name(x509.Name([
x509.NameAttribute(NameOID.COUNTRY_NAME, C),
x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, ST),
x509.NameAttribute(NameOID.LOCALITY_NAME, L),
x509.NameAttribute(NameOID.ORGANIZATION_NAME, O),
x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, OU),
x509.NameAttribute(NameOID.COMMON_NAME, CN),
]))
# SAN
san = [x509.DNSName(i) for i in SANS]
csr = csr.add_extension(
x509.SubjectAlternativeName(san),
critical=False,
)
# CA签名CSR
new_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048,
backend=default_backend()
)
csr = csr.sign(new_key, hashes.SHA256(), default_backend())
builder = CertificateBuilder()
builder = builder.issuer_name(csr.subject)
builder = builder.subject_name(csr.subject)
builder = builder.public_key(csr.public_key())
builder = builder.serial_number(x509.random_serial_number())
builder = builder.not_valid_before(datetime.datetime.utcnow())
builder = builder.not_valid_after(datetime.datetime.utcnow() + datetime.timedelta(days=days))
builder = builder.add_extension(
x509.SubjectAlternativeName(san),
critical=False,
)
# 签发证书
with open(root_key, "rb") as key_file:
ca_private_key = serialization.load_pem_private_key(
key_file.read(),
password=None,
backend=default_backend()
)
cert = builder.sign(ca_private_key, hashes.SHA256(), default_backend())
_crt = cert.public_bytes(Encoding.PEM)
# 生成证书链
_crt = _crt + open(root_crt, 'rb').read()
# 私钥PEM格式
_key = new_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.TraditionalOpenSSL,
encryption_algorithm=serialization.NoEncryption()
)
return _crt, _key
if __name__ == '__main__':
_crt, _key = generate_ssl(
C='CN', ST='Shanghai', L='Shanghai', O='', OU='', CN='192.168.176.138', days=730,
SANS=['192.168.176.138', '192.168.1.1']
)
print(_crt.decode())
print(_key.decode())