Python
我在'sCryptography
模块中编写了执行以下操作的代码:
a) 生成rootCA
和根证书
b) 生成客户端密钥
Certificate Signing Request
c)使用密钥创建一个
d) 使用rootCA
第一步生成的CSR
,第三步创建的,生成我自己创建的root签名的证书。
执行此操作的代码如下所示:
from cryptography import x509
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.serialization import load_der_private_key
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.x509.oid import NameOID
import datetime
import uuid
import os
import sys
import subprocess
def generate_root_CA():
"""
a) generate rootCA key
b) generate rootCA crt
"""
##generating root key
root_private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048,
backend=default_backend())
##self-sign and generate the root certificate
root_public_key = root_private_key.public_key()
builder = x509.CertificateBuilder()
builder = builder.subject_name(x509.Name([
x509.NameAttribute(NameOID.COMMON_NAME, u'Test CA'),
x509.NameAttribute(NameOID.ORGANIZATION_NAME, u'Org'),
x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, u'Testing unit'),
]))
builder = builder.issuer_name(x509.Name([
x509.NameAttribute(NameOID.COMMON_NAME, u'Test CA'),
]))
builder = builder.not_valid_before(datetime.datetime.today() - datetime.timedelta(days=1))
builder = builder.not_valid_after(datetime.datetime(2019, 12, 31))
builder = builder.serial_number(int(uuid.uuid4()))
builder = builder.public_key(root_public_key)
builder = builder.add_extension(
x509.BasicConstraints(ca=True, path_length=None), critical=True,)
root_certificate = builder.sign(
private_key=root_private_key, algorithm=hashes.SHA256(),
backend=default_backend()
)
##write to disk
with open("rootCA.key", "wb") as f:
f.write(root_private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.TraditionalOpenSSL,
encryption_algorithm=serialization.BestAvailableEncryption(b"passphrase")
))
with open("rootCA.crt", "wb") as f:
f.write(root_certificate.public_bytes(
encoding=serialization.Encoding.PEM,
))
return root_private_key, root_certificate
def generate_key():
"""
a) generate key for the certificate being created
"""
key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048,
backend=default_backend()
)
return key
def generate_csr(key, domain_name):
"""
generate csr for the client certificate
"""
csr = x509.CertificateSigningRequestBuilder().subject_name(x509.Name([
# Provide various details about who we are.
x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"MA"),
x509.NameAttribute(NameOID.LOCALITY_NAME, u"Boston"),
x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"Org"),
x509.NameAttribute(NameOID.COMMON_NAME, domain_name),
])).add_extension(
x509.SubjectAlternativeName([
x509.DNSName(domain_name),
x509.DNSName(u"www." + domain_name),
]),
critical=False,
# Sign the CSR with our private key.
).sign(key, hashes.SHA256(), default_backend())
# Write our CSR out to disk.
with open(domain_name + ".csr", "wb") as f:
f.write(csr.public_bytes(serialization.Encoding.PEM))
return csr
def sign_certificate_request(csr, rootkey, rootcrt, client_key, domain_name):
"""
generate the certificate based on the csr created
"""
crt = x509.CertificateBuilder().subject_name(
csr.subject
).issuer_name(
rootcrt.subject
).public_key(
csr.public_key()
).serial_number(
uuid.uuid4().int # pylint: disable=no-member
).not_valid_before(
datetime.datetime.utcnow()
).not_valid_after(
datetime.datetime.utcnow() + datetime.timedelta(days=2)
).add_extension(
extension=x509.KeyUsage(
digital_signature=True, key_encipherment=True, content_commitment=True,
data_encipherment=False, key_agreement=False, encipher_only=False, decipher_only=False, key_cert_sign=False, crl_sign=False
),
critical=True
).add_extension(
extension=x509.BasicConstraints(ca=False, path_length=None),
critical=True
).add_extension(
extension=x509.AuthorityKeyIdentifier.from_issuer_public_key(rootkey.public_key()),
critical=False
).sign(
private_key=rootkey,
algorithm=hashes.SHA256(),
backend=default_backend()
)
with open(domain_name + ".crt", 'wb') as f:
f.write(crt.public_bytes(encoding=serialization.Encoding.PEM))
def main():
domain_name = "domain.org"
root_key, root_crt = generate_root_CA()
domain_key = generate_key()
csr = generate_csr(domain_key, domain_name)
sign_certificate_request(csr, root_key, root_crt, domain_key, domain_name)
if __name__ == "__main__":
main()
但是,ssl.SSLError: [X509: KEY_VALUES_MISMATCH] key values mismatch (_ssl.c:2798)
当我使用本地flask
应用程序进行测试时出现错误。我无法弄清楚错误。在签署证书时,我使用根证书的私钥和我的域的公钥作为另一个参数,这是否可能导致问题?
编辑:
我能够通过此链接中的以下两条说明(来自链接的引用)检查是否确实存在生成密钥的错误:
1- first command for getting the decryption of your server certificate:
openssl x509 -noout -modulus -in /etc/yourcertificate.crt | openssl md5
2- 2nd command for your (RSA) private key you got from creating csr:
openssl rsa -noout -modulus -in /etc/private.key | openssl md5
他们确实不同。传输正确的密钥时出现了一些错误,我能够重新运行代码以得到md5
相同的密钥。