[英]Unable to verify the CA signed SSL certificate python web server
[英]Python cryptography: create a certificate signed by an existing CA, and export
我正在創建一個像這樣的 CA:
openssl genrsa -out ca.key 4096
openssl req -new -x509 -days 3650 -key ca.key -out ca.cert
這給了我兩個 PEM 文件。
然后我調用這個函數,其中cert_authority
和private_key
是上面生成的數據的字符串。
def create_cert(cert_authority, private_key):
one_day = datetime.timedelta(1, 0, 0)
# Use our private key to generate a public key
private_key = serialization.load_pem_private_key(
private_key.encode("ascii"), password=None, backend=default_backend()
)
public_key = private_key.public_key()
ca = x509.load_pem_x509_certificate(
cert_authority.encode("ascii"), default_backend()
)
builder = x509.CertificateBuilder()
builder = builder.subject_name(
x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io")])
)
builder = builder.issuer_name(ca.issuer)
builder = builder.not_valid_before(datetime.datetime.today() - one_day)
builder = builder.not_valid_after(datetime.datetime.today() + (one_day * 30))
builder = builder.serial_number(x509.random_serial_number())
builder = builder.public_key(public_key)
cert = builder.sign(
private_key=private_key, algorithm=hashes.SHA256(), backend=default_backend()
)
print(cert.public_bytes(serialization.Encoding.PEM))
然后,這會生成似乎是證書的內容,但是將數據復制並粘貼到文件中(並按http://srdevspot.blogspot.com/2011/08/openssl-error0906d064pem包裝 64 行並使用 Unix 換行符。 html ) 嘗試驗證時出現此錯誤:
$ openssl verify -CAfile ca.crt -untrusted phone.crt
unable to load certificates
希望我錯過了一些簡單的東西,因為我是這一切的新手!
最后我會注意到,如果密碼學不是最好的,我願意使用另一個加密庫。
編輯:
現在根據保羅非常有用的回應使用這個:
def create_cert(cert_authority, private_key):
one_day = datetime.timedelta(1, 0, 0)
# Use our private key to generate a public key
root_key = serialization.load_pem_private_key(
private_key.encode("ascii"), password=None, backend=default_backend()
)
root_cert = x509.load_pem_x509_certificate(
cert_authority.encode("ascii"), default_backend()
)
# Now we want to generate a cert from that root
cert_key = rsa.generate_private_key(
public_exponent=65537, key_size=2048, backend=default_backend()
)
new_subject = x509.Name(
[
x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"Texas"),
x509.NameAttribute(NameOID.LOCALITY_NAME, u"Austin"),
x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"New Org Name!"),
]
)
cert = (
x509.CertificateBuilder()
.subject_name(new_subject)
.issuer_name(root_cert.issuer)
.public_key(cert_key.public_key())
.serial_number(x509.random_serial_number())
.not_valid_before(datetime.datetime.utcnow())
.not_valid_after(datetime.datetime.utcnow() + datetime.timedelta(days=30))
.add_extension(
x509.SubjectAlternativeName([x509.DNSName(u"somedomain.com")]),
critical=False,
)
.sign(root_key, hashes.SHA256(), default_backend())
)
# Dump to scratch
with open("scratch/phone_cert.pem", "wb") as f:
f.write(cert.public_bytes(encoding=serialization.Encoding.PEM))
# Return PEM
cert_pem = cert.public_bytes(encoding=serialization.Encoding.PEM)
cert_key_pem = cert_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.TraditionalOpenSSL,
encryption_algorithm=serialization.NoEncryption(),
)
return cert_pem, cert_key_pem
這是保存文件並將創建的證書和私鑰作為 PEM 字符串返回的正確方法嗎?
我還發現,當我嘗試使用openssl verify -verbose -CAfile ca.crt -untrusted phone_cert.pem
針對保存的 PEM 驗證創建的證書時,該命令永遠不會返回 - 可能是一個單獨的問題,但會感謝任何想法。
我在這里看到了兩個問題。 首先,您正在創建另一個自簽名證書,因此您生成的證書不是由 CA 簽名的,它本身就是一個 CA。 要糾正此問題,您需要使用 CA 的私鑰(例如,在您的示例中為private_key
)進行簽名,但您需要創建一個與新證書關聯的新私鑰,並將其公鑰嵌入到證書中。
certificate_private_key = <generate an ec or rsa key here>
certificate_public_key = certificate_private_key.public_key()
然后做
builder = builder.public_key(certificate_public_key)
您的輸出也有問題,因為您試圖從打印語句中復制和粘貼內容。 cert.public_bytes(serialization.Encoding.PEM)
的輸出將是一個有效的 X509 證書,帶有分隔符和正確的 PEM 行長度,因此將其直接寫入文件:
with open("cert.crt", "wb") as f:
f.write(cert.public_bytes(serialization.Encoding.PEM))
結果可以用openssl x509 -noout -text -in cert.crt
這是一個完整的示例,它利用cryptography
創建自簽名根 CA 並使用該 CA 簽署證書。
import datetime
from cryptography import x509
from cryptography.x509.oid import NameOID
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa
root_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048,
backend=default_backend()
)
subject = issuer = x509.Name([
x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"Texas"),
x509.NameAttribute(NameOID.LOCALITY_NAME, u"Austin"),
x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"My Company"),
x509.NameAttribute(NameOID.COMMON_NAME, u"My CA"),
])
root_cert = x509.CertificateBuilder().subject_name(
subject
).issuer_name(
issuer
).public_key(
root_key.public_key()
).serial_number(
x509.random_serial_number()
).not_valid_before(
datetime.datetime.utcnow()
).not_valid_after(
datetime.datetime.utcnow() + datetime.timedelta(days=3650)
).sign(root_key, hashes.SHA256(), default_backend())
# Now we want to generate a cert from that root
cert_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048,
backend=default_backend()
)
new_subject = x509.Name([
x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"Texas"),
x509.NameAttribute(NameOID.LOCALITY_NAME, u"Austin"),
x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"New Org Name!"),
])
cert = x509.CertificateBuilder().subject_name(
new_subject
).issuer_name(
root_cert.issuer
).public_key(
cert_key.public_key()
).serial_number(
x509.random_serial_number()
).not_valid_before(
datetime.datetime.utcnow()
).not_valid_after(
datetime.datetime.utcnow() + datetime.timedelta(days=30)
).add_extension(
x509.SubjectAlternativeName([x509.DNSName(u"somedomain.com")]),
critical=False,
).sign(root_key, hashes.SHA256(), default_backend())
因為我是新手,所以我必須發布一個答案,還不能發表評論🙄
我非常依賴 Pauls 的回答來進行我自己的實施,這非常有用且很有幫助。 但是我必須在 CA 證書上再添加一個擴展名,以便openssl verify -verbose -CAfile ca.crt client.crt
正常工作。
將.add_extension(x509.BasicConstraints(ca=True, path_length=None), critical=True)
到根 CertificateBuilder 就可以了。
ca_crt = x509.CertificateBuilder() \
.subject_name(subject) \
.issuer_name(issuer) \
.public_key(ca_key.public_key()) \
.serial_number(x509.random_serial_number()) \
.not_valid_before(datetime.datetime.today() - one_day) \
.not_valid_after(datetime.datetime.today() + (one_day * 365)) \
.add_extension(x509.BasicConstraints(ca=True, path_length=None), critical=True) \
.sign(ca_key, hashes.SHA256(), default_backend())
其他一切都像保羅一樣。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.