def generate_adhoc_ssl_pair(cn=None):
from datetime import datetime as dt
from datetime import timedelta
try:
from cryptography import x509
from cryptography.x509.oid import NameOID
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import rsa
except ImportError:
raise TypeError("Using ad-hoc certificates requires the cryptography library.")
pkey = rsa.generate_private_key(
public_exponent=65537, key_size=2048, backend=default_backend()
)
# pretty damn sure that this is not actually accepted by anyone
if cn is None:
cn = u"*"
# subject:使用者
subject = x509.Name(
[
x509.NameAttribute(NameOID.ORGANIZATION_NAME, "我自己"),
x509.NameAttribute(NameOID.COMMON_NAME, '127.0.0.1'),
x509.NameAttribute(NameOID.COUNTRY_NAME, 'cn'),
]
)
# issuer:颁发者
issuer = x509.Name(
[
x509.NameAttribute(NameOID.ORGANIZATION_NAME, "我自己"),
x509.NameAttribute(NameOID.COMMON_NAME, '127.0.0.1'),
x509.NameAttribute(NameOID.COUNTRY_NAME, 'cn'),
]
)
# cert使用私钥签名(.sign(私钥,摘要生成算法,填充方式)),使用x509.CertificateBuilder()方法生成证书,证书属性使用下列函数叠加补充
cert = (
x509.CertificateBuilder()
.subject_name(subject)
.issuer_name(issuer)
.public_key(pkey.public_key())
.serial_number(x509.random_serial_number())
.not_valid_before(dt.utcnow() + timedelta())
.not_valid_after(dt.utcnow() + timedelta(days=365)).sign(pkey, hashes.SHA256(), default_backend())
)
# 最终生成的证书与密钥对为类对象,要保存在文件中还需要进一步转换成字节格式
return cert, pkey
if __name__ == '__main__':
import OpenSSL
from cryptography.hazmat.primitives import serialization
cert, pkey = generate_adhoc_ssl_pair()
print(cert)
# 将证书类对象转换成PEM格式的字节串
cert_text = cert.public_bytes(serialization.Encoding.PEM)
print(cert_text)
# 将证书字节串保存到文件中
with open('self_signed.cer', mode='wb') as cert_file:
cert_file.write(cert_text)
# 将私钥类对象转换成PEM格式的字节串,encryption_algorithm=serialization.NoEncryption()这里是私钥不加密的意思
private_text = pkey.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.TraditionalOpenSSL,
encryption_algorithm=serialization.NoEncryption()
)
print(private_text)
# 将私钥字节串保存到文件中
with open('self_signed_pkey.key', mode='wb') as pkey_file:
pkey_file.write(private_text)
# 在程序中查看证书文件内容,当然也可以在文件夹中去双击self_signed.cer查看
cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM,
cert_text)
certIssue = cert.get_issuer()
print("通用名称: ", cert.get_subject().CN)
print("机构名: ", cert.get_subject().O)
print("机构单元名称: ", cert.get_subject().OU)
print("地理位置: ", cert.get_subject().L)
print("州/省名: ", cert.get_subject().ST)
print("国名: ", cert.get_subject().C)
print("证书版本: ", cert.get_version() + 1)
print("证书序列号: ", hex(cert.get_serial_number()))
print("证书中使用的签名算法: ", cert.get_signature_algorithm().decode("UTF-8"))
print("颁发者: ", certIssue.commonName)
print("有效期从: ", cert.get_notBefore())
print("到: ", cert.get_notAfter())
print("证书是否已经过期: ", cert.has_expired())
print("公钥长度", cert.get_pubkey().bits())
print("公钥:\n", OpenSSL.crypto.dump_publickey(OpenSSL.crypto.FILETYPE_PEM,
cert.get_pubkey()).decode(
"utf-8"))
print("主体信息:")
print("CN : 通用名称 OU : 机构单元名称")
print("O : 机构名 L : 地理位置")
print("S : 州/省名 C : 国名")
for item in certIssue.get_components():
print(item[0].decode("utf-8"), " —— ", item[1].decode("utf-8"))
print(cert.get_extension_count())
python证书生成篇
于 2022-01-26 11:49:18 首次发布