searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

使用python创建一个私有CA

2023-07-04 08:52:54
85
0

参考 OpenSSL Cookbook - Creating a Private Certification Authority,使用 OpenSSL 命令行可以创建一个私有CA。

本文则基于python的cryptography库,编写一个简单的私有CA,并用其来签发一套测试使用的证书。

创建自签发的root CA

普通证书的签发需要使用 CA的私钥对其进行私钥加密,root CA由于位于该条信任链的起始,只能使用自身的私钥对其进行签发,即自签发证书。

自签发证书遵循以下步骤

  1. 生成私钥
  2. 使用私钥对自身进行签发

genRootCA.py:

from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography import x509
from cryptography.x509.oid import NameOID
from cryptography.hazmat.primitives import hashes
import datetime

# 生成 2048 位 rsa 私钥
key = rsa.generate_private_key(
    public_exponent=65537,
    key_size=2048,
)

# 保存私钥到磁盘,并使用 key pass 进行加密
with open("rootca.key.secure", "wb") as f:
    f.write(key.private_bytes(
        encoding=serialization.Encoding.PEM,
        format=serialization.PrivateFormat.TraditionalOpenSSL,
        encryption_algorithm=serialization.BestAvailableEncryption(b"12345678")
    ))

# Various details about who we are. For a self-signed certificate the
# subject and issuer are always the same.
subject = issuer = x509.Name([
    x509.NameAttribute(NameOID.COUNTRY_NAME, u"CN"),
    x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"Sichuan"),
    x509.NameAttribute(NameOID.LOCALITY_NAME, u"Chengdu"),
    x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"ctyun elb"),
    x509.NameAttribute(NameOID.COMMON_NAME, u"test root CA"),
])
cert = x509.CertificateBuilder().subject_name(
    subject
).issuer_name(
    issuer
).public_key(
    key.public_key()
).serial_number(
    x509.random_serial_number()
).not_valid_before(
    datetime.datetime.utcnow()
).not_valid_after(
    # Our certificate will be valid for 1 years default
    datetime.datetime.utcnow() + datetime.timedelta(365)
).add_extension(
    x509.SubjectAlternativeName([x509.DNSName(u"localhost")]),
    critical=False,
# 使用root CA的私钥签发root CA证书
).sign(key, hashes.SHA256())
# 保存证书到磁盘
with open("rootca.pem", "wb") as f:
    f.write(cert.public_bytes(serialization.Encoding.PEM))

执行程序

python3 genRootCA.py

得到受密码保护的RSA私钥(rootca.key.secure)和证书(rootca.pem)

使用root CA签发普通证书

root CA我们使用上一步得到的 rootca.key.secure 和 rootca.pem。

普通证书签发遵循以下步骤

  1. 加载CA私钥
  2. 生成私钥
  3. 使用CA私钥对证书进行签发

genCert.py:

from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography import x509
from cryptography.x509.oid import NameOID
from cryptography.hazmat.primitives import hashes
import datetime

# 加载 root CA 的证书与私钥
with open("rootca.pem", 'rb') as f:
    datas = f.read()
    cacert = x509.load_pem_x509_certificate(datas)
with open("rootca.key.secure", 'rb') as f:
    datas = f.read()
    cakey = serialization.load_pem_private_key(datas,b'12345678')

# 生成 2048 位 rsa 私钥
key = rsa.generate_private_key(
    public_exponent=65537,
    key_size=2048,
)

# 保存私钥到磁盘,并使用 key pass 进行加密
with open("www.example.com.key.secure", "wb") as f:
    f.write(key.private_bytes(
        encoding=serialization.Encoding.PEM,
        format=serialization.PrivateFormat.TraditionalOpenSSL,
        encryption_algorithm=serialization.BestAvailableEncryption(b"12345678")
    ))

# 保存私钥到磁盘,不加密
with open("www.example.com.key.unsecure", "wb") as f:
    f.write(key.private_bytes(
        encoding=serialization.Encoding.PEM,
        format=serialization.PrivateFormat.TraditionalOpenSSL,
        encryption_algorithm=serialization.NoEncryption()
    ))

# Various details about who we are. For a self-signed certificate the
# subject and issuer are always the same.
subject = issuer = x509.Name([
    x509.NameAttribute(NameOID.COUNTRY_NAME, u"CN"),
    x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"Sichuan"),
    x509.NameAttribute(NameOID.LOCALITY_NAME, u"Chengdu"),
    x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"ctyun elb"),
    x509.NameAttribute(NameOID.COMMON_NAME, u"www.example.com"),
])
cert = x509.CertificateBuilder().subject_name(
    subject
).issuer_name(
    cacert.subject
).public_key(
    key.public_key()
).serial_number(
    x509.random_serial_number()
).not_valid_before(
    datetime.datetime.utcnow()
).not_valid_after(
    # Our certificate will be valid for 1 years default
    datetime.datetime.utcnow() + datetime.timedelta(365)
).add_extension(
    x509.SubjectAlternativeName([x509.DNSName(u"example.com")]),
    critical=False,
# 使用root CA的私钥签发root CA证书
).sign(cakey, hashes.SHA256())
# 保存证书到磁盘
with open("www.example.com.pem", "wb") as f:
    f.write(cert.public_bytes(serialization.Encoding.PEM))

执行程序

python3 genCert.py

得到受密码保护的RSA私钥(www.example.com.key.secure)、不受密码保护的RSA私钥(www.example.com.key.unsecure)和证书(www.example.com.pem)

 

这里提供一个更加完善的程序:orzPrivateCA

0条评论
0 / 1000
renz2048
2文章数
0粉丝数
renz2048
2 文章 | 0 粉丝
renz2048
2文章数
0粉丝数
renz2048
2 文章 | 0 粉丝
原创

使用python创建一个私有CA

2023-07-04 08:52:54
85
0

参考 OpenSSL Cookbook - Creating a Private Certification Authority,使用 OpenSSL 命令行可以创建一个私有CA。

本文则基于python的cryptography库,编写一个简单的私有CA,并用其来签发一套测试使用的证书。

创建自签发的root CA

普通证书的签发需要使用 CA的私钥对其进行私钥加密,root CA由于位于该条信任链的起始,只能使用自身的私钥对其进行签发,即自签发证书。

自签发证书遵循以下步骤

  1. 生成私钥
  2. 使用私钥对自身进行签发

genRootCA.py:

from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography import x509
from cryptography.x509.oid import NameOID
from cryptography.hazmat.primitives import hashes
import datetime

# 生成 2048 位 rsa 私钥
key = rsa.generate_private_key(
    public_exponent=65537,
    key_size=2048,
)

# 保存私钥到磁盘,并使用 key pass 进行加密
with open("rootca.key.secure", "wb") as f:
    f.write(key.private_bytes(
        encoding=serialization.Encoding.PEM,
        format=serialization.PrivateFormat.TraditionalOpenSSL,
        encryption_algorithm=serialization.BestAvailableEncryption(b"12345678")
    ))

# Various details about who we are. For a self-signed certificate the
# subject and issuer are always the same.
subject = issuer = x509.Name([
    x509.NameAttribute(NameOID.COUNTRY_NAME, u"CN"),
    x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"Sichuan"),
    x509.NameAttribute(NameOID.LOCALITY_NAME, u"Chengdu"),
    x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"ctyun elb"),
    x509.NameAttribute(NameOID.COMMON_NAME, u"test root CA"),
])
cert = x509.CertificateBuilder().subject_name(
    subject
).issuer_name(
    issuer
).public_key(
    key.public_key()
).serial_number(
    x509.random_serial_number()
).not_valid_before(
    datetime.datetime.utcnow()
).not_valid_after(
    # Our certificate will be valid for 1 years default
    datetime.datetime.utcnow() + datetime.timedelta(365)
).add_extension(
    x509.SubjectAlternativeName([x509.DNSName(u"localhost")]),
    critical=False,
# 使用root CA的私钥签发root CA证书
).sign(key, hashes.SHA256())
# 保存证书到磁盘
with open("rootca.pem", "wb") as f:
    f.write(cert.public_bytes(serialization.Encoding.PEM))

执行程序

python3 genRootCA.py

得到受密码保护的RSA私钥(rootca.key.secure)和证书(rootca.pem)

使用root CA签发普通证书

root CA我们使用上一步得到的 rootca.key.secure 和 rootca.pem。

普通证书签发遵循以下步骤

  1. 加载CA私钥
  2. 生成私钥
  3. 使用CA私钥对证书进行签发

genCert.py:

from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography import x509
from cryptography.x509.oid import NameOID
from cryptography.hazmat.primitives import hashes
import datetime

# 加载 root CA 的证书与私钥
with open("rootca.pem", 'rb') as f:
    datas = f.read()
    cacert = x509.load_pem_x509_certificate(datas)
with open("rootca.key.secure", 'rb') as f:
    datas = f.read()
    cakey = serialization.load_pem_private_key(datas,b'12345678')

# 生成 2048 位 rsa 私钥
key = rsa.generate_private_key(
    public_exponent=65537,
    key_size=2048,
)

# 保存私钥到磁盘,并使用 key pass 进行加密
with open("www.example.com.key.secure", "wb") as f:
    f.write(key.private_bytes(
        encoding=serialization.Encoding.PEM,
        format=serialization.PrivateFormat.TraditionalOpenSSL,
        encryption_algorithm=serialization.BestAvailableEncryption(b"12345678")
    ))

# 保存私钥到磁盘,不加密
with open("www.example.com.key.unsecure", "wb") as f:
    f.write(key.private_bytes(
        encoding=serialization.Encoding.PEM,
        format=serialization.PrivateFormat.TraditionalOpenSSL,
        encryption_algorithm=serialization.NoEncryption()
    ))

# Various details about who we are. For a self-signed certificate the
# subject and issuer are always the same.
subject = issuer = x509.Name([
    x509.NameAttribute(NameOID.COUNTRY_NAME, u"CN"),
    x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"Sichuan"),
    x509.NameAttribute(NameOID.LOCALITY_NAME, u"Chengdu"),
    x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"ctyun elb"),
    x509.NameAttribute(NameOID.COMMON_NAME, u"www.example.com"),
])
cert = x509.CertificateBuilder().subject_name(
    subject
).issuer_name(
    cacert.subject
).public_key(
    key.public_key()
).serial_number(
    x509.random_serial_number()
).not_valid_before(
    datetime.datetime.utcnow()
).not_valid_after(
    # Our certificate will be valid for 1 years default
    datetime.datetime.utcnow() + datetime.timedelta(365)
).add_extension(
    x509.SubjectAlternativeName([x509.DNSName(u"example.com")]),
    critical=False,
# 使用root CA的私钥签发root CA证书
).sign(cakey, hashes.SHA256())
# 保存证书到磁盘
with open("www.example.com.pem", "wb") as f:
    f.write(cert.public_bytes(serialization.Encoding.PEM))

执行程序

python3 genCert.py

得到受密码保护的RSA私钥(www.example.com.key.secure)、不受密码保护的RSA私钥(www.example.com.key.unsecure)和证书(www.example.com.pem)

 

这里提供一个更加完善的程序:orzPrivateCA

文章来自个人专栏
https
2 文章 | 1 订阅
0条评论
0 / 1000
请输入你的评论
0
0