对于 HTTPS 可访问服务的本地测试,我正在使用以下程序生成自己的密钥和证书。毫无疑问,该程序构建的证书在各种方面都不符合现实世界证书的最佳实践。但是,导致 Chrome 以这种“不符合安全标准”的错误拒绝它们的特定问题让我无法理解。
Chrome 报告的完整(较少域)错误是:
生成证书、密钥等的程序是:
#!/usr/bin/env python
from __future__ import unicode_literals, print_function
from string import uppercase
from datetime import datetime, timedelta
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.x509.oid import NameOID
from cryptography.hazmat.primitives.hashes import SHA256
from cryptography.hazmat.primitives import serialization
from cryptography.x509 import (
CertificateBuilder,
SubjectAlternativeName,
BasicConstraints,
DNSName,
Name,
NameAttribute,
)
from cryptography.hazmat.backends import default_backend
def cert(issuer, subject, issuer_key, subject_key, ca):
builder = CertificateBuilder(
).issuer_name(
Name([NameAttribute(NameOID.COMMON_NAME, issuer)]),
).subject_name(
Name([NameAttribute(NameOID.COMMON_NAME, subject)]),
).add_extension(
SubjectAlternativeName([DNSName(subject)]),
critical=False,
)
if ca:
builder = builder.add_extension(
BasicConstraints(True, None),
critical=True,
)
return builder.public_key(subject_key.public_key(),
).serial_number(1,
).not_valid_before(datetime.utcnow(),
).not_valid_after(datetime.utcnow() + timedelta(days=365),
).sign(issuer_key, SHA256(), default_backend(),
)
def main(num_certs, subject_name):
keys = tuple(
rsa.generate_private_key(
public_exponent=65537,
key_size=1024,
backend=default_backend(),
)
for i in range(num_certs)
)
names = list(
ch + ".invalid"
for ch
in uppercase.decode("ascii")[:len(keys) - 1]
) + [subject_name]
certs = tuple(
cert(
issuer=issuer_name,
subject=subject_name,
issuer_key=issuer_key,
subject_key=subject_key,
ca=is_ca,
)
for (issuer_name, subject_name, issuer_key, subject_key, is_ca)
in zip(
names[:1] + names[:-1],
names,
keys[:1] + keys[:-1],
keys,
range(len(keys) - 1, -1, -1),
)
)
print("\n".join(
key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.TraditionalOpenSSL,
encryption_algorithm=serialization.NoEncryption(),
for key
in keys
))
print("\n".join(
cert.public_bytes(serialization.Encoding.PEM)
for cert
in certs
))
main(3, "<some domain name>")
该程序吐出密钥,然后是证书。在链长度为 3 的默认设置下,有一个 CA 密钥/证书、一个中间密钥/证书和一个服务器密钥/证书。
这是它的输出示例:
-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQCx5455hmlbJ/jWgZDuoPy6ymVSHarTOmSMYWp9jTae3Y5t7WEB
8mYdjW/3kZbr8+GVj2gSVHPdQMQdLMwgGmZKnG0VmiZsjHBBu3TA4ZymNGCppUPy
+z4stSEhLA+m0x8yAGt5qorbHcWo9rQnSXTtLD0RlGS4SUutxXaYF88sVwIDAQAB
AoGATvHsPW0x72uLdtTEFcCGpfUOhSP5HAa7e7f244P4iwLSI2HFPHHucorC9t86
U7ZDknSyv/+N8s68uB2a71wHq7JXwRzaU49sQk5NcPHgT5VjYPKtyL+0eY1hXqcn
zzIYRxtFAYiJXPa2ghKHBuP/tpMXMhIkMmMyfYJfd2a9YXECQQDlt7s010CvQcBu
wxa1riZUhp/a5MaaRPMJrJ0H8FFD34i953p0bddyyybSEyNpTfFTF42dfIAgLNDb
YeJj+wLTAkEAxkJA/F5TcXAxdEXtJgXU1zdzEfvrUFNfFR1Vf/Kzkr0618FqQZWL
lLHckqcqH4I+vdw2ycy7kpY0JDkRIBzV7QJAN5+WkAPzILy+GNPaYuGpXFxAxuMQ
h/hcFSKb33k8ZD/zP3CWgSy7t4sjekiyEWSTI7iXTOQBrkjLxeNcyzLTiwJAdHiV
vu0XLkxP8VPnNvA0Et9TbZxGqKDh+gCKqykEz871U60f5Dmbj5ZR06H7ABm/DEDj
uvfYtgwhw6n24puuHQJBAKSAxj+qsjRk8fK9J6GKZ+qaMNEQlzHdQH9LVjzlCSlP
r9GkzmdLnlfVPck3ytJhkgYWQgSE3eh45kGkDOkGZ8U=
-----END RSA PRIVATE KEY-----
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDZPrkocPoakI93K2Z3pF8rHaq6L84ZG7o0UbWu5zgXc64PhBFU
xALTRbcGTVhIjViJKDue7iYq5/5TfGOXsF3gXxcXt5OQT9JN1t42T1FzuKxVwgg5
vXqjGFHLZJqBNCG6wGuD4R7/wPro7Pt3rVEMSt9tLvb+CF53LbTM0SyJFQIDAQAB
AoGACk8lrjueQsB1bmxK0oakVYF05pz6JMriDTWLb59dVA+TRP05bVJX5/q48r2c
4OSEPQ4BtksK2KJluUR/3WTrL3Ii562zmNYWAZ6BM+aBt/FZDQY01og4kLVnOfU+
NRyhOThogIvXLCiUMNTTixZ7wO7TYa0bJc0tLBr0Guwk5YkCQQD9gG06iV4P7EfI
hHwR6q6tjGs54UVCWras26iKvb9Kob9DWIR510NowUZ5ALVAyWT9mpJvZy4+E6I4
O6lugpfLAkEA22LSm7h+1Ck3kVQYwvKrG9XNSe7rgPYH6mWPogoAZxXO53K74Hih
h8ZG/+JmuQOA5TJf5N1xRAncr6cUjFSGnwJBAM0SzMozAEYPVg7PpnL0EDVTSBb9
twKz0d3KoPEECTD94nU/sYPDccPXvwP6X6a2hZ1nIxk+Njl/tpaZJTrCKLsCQEvf
78sfke26m5dNqIqz9u3XkfqCAT1G2hH9MiHup5j/d+GgUs4dqnAU6TVSjghq58dd
FsFGvQe1CXhOptKp4S0CQQDy5yZ3qmtLhtGfO+c84skkxjcnwHwSR82tbBWaBpqo
tC2UYL7MrXBoNF/bgES+DKF5AdUqHyU6ecU0oq4eVY2f
-----END RSA PRIVATE KEY-----
-----BEGIN RSA PRIVATE KEY-----
MIICWwIBAAKBgQC4fK/bPNx/M5lu0EL5iwFYB2wy+gpgBrnj77IRoDrtrOyBIiOa
LN+iBzxuINflFX+dFPqLGEc15Kuxe+HyZZDG9XOFt3qZ/0ijoi/x7BB1ZaNxGsF+
Tj4HAvEKKYjUz54cjnhDpt5ZOcJXbAYMNIODBMJJX8Ghg+K7whBQnqFSFQIDAQAB
AoGAIE7NqTI2VxxdMVfNctASEy1xmFfLe1eSNEWkxItv5nGTFWY6H+Td4Q0tWwfr
ZxXlvEeRPMyqo9iA7NsKDZ4VxUW1VBw8Cw4Ua5RDtsRZUL9wc16Wk0y5pwCjWDrP
DI8yRBGmtx+5uY0CNeYQ0mQA1SHC9KtrDRC2kHIDfYN3nh0CQQDmc5/nBV0RTjKs
EdeiRlhAuwEC2zwNQYF/xZzfL9PS65t13Rm1mW2G75RMrjFJclXe+y/SdAibYNJi
lucSsckLAkEAzPCOOvxKjjXTeCyfc1fAYZMOhz/oMy4t+qy2Yc6Lp6DJrhR3T3JC
9qjaLh2a+OnwIPrn5EGQWSLXlSSHNr+FXwJAWWV7HzQ+cSsjjwpw2tts+tdQQhpn
xkCmCrnO6+lyw3xwVx2JDqBRE6o2njRonDRFSXWpjHtEp3m8w1AEnYToFwJAfVFf
98vMn1dkv6ixvCtdtYziJmw6xgkoDpBMWlSd61wT14ImTwt0zTYFbIun9yu+Lbyf
zmEVLpxyrX2PvTeyCwJAP1bQmjTVTMv1ahn9QvarbsqlOV3lMbiyfHREVAGON9LA
e8UCAlL1u0RuV2lqhK8rlkMqxUuZ/D6uDlLrTJpCew==
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIIByjCCATOgAwIBAgIEWVRCgjANBgkqhkiG9w0BAQsFADAUMRIwEAYDVQQDDAlB
LmludmFsaWQwHhcNMTcwNjI4MjM1NzU0WhcNMTgwNjI4MjM1NzU0WjAUMRIwEAYD
VQQDDAlBLmludmFsaWQwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALHnjnmG
aVsn+NaBkO6g/LrKZVIdqtM6ZIxhan2NNp7djm3tYQHyZh2Nb/eRluvz4ZWPaBJU
c91AxB0szCAaZkqcbRWaJmyMcEG7dMDhnKY0YKmlQ/L7Piy1ISEsD6bTHzIAa3mq
itsdxaj2tCdJdO0sPRGUZLhJS63FdpgXzyxXAgMBAAGjKTAnMBQGA1UdEQQNMAuC
CUEuaW52YWxpZDAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4GBADfL
MQitgG+iFEraLMoXzkO65T1JnKIY4rnpW6bJP0Mt2PaSCzvH3AlPnA7ZGvw+x5+b
EdhaxiY3sweSfbRaYubhDHaL8lNB0So4SP1hVFNFQjSLR1aGqoeqY7IYhIzpQ5MK
Pb+sYmvdko45431t8GJOkb9Pg7N/o1aRfzCK2Lca
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIByjCCATOgAwIBAgIEWVRCgjANBgkqhkiG9w0BAQsFADAUMRIwEAYDVQQDDAlB
LmludmFsaWQwHhcNMTcwNjI4MjM1NzU0WhcNMTgwNjI4MjM1NzU0WjAUMRIwEAYD
VQQDDAlCLmludmFsaWQwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANk+uShw
+hqQj3crZnekXysdqrovzhkbujRRta7nOBdzrg+EEVTEAtNFtwZNWEiNWIkoO57u
Jirn/lN8Y5ewXeBfFxe3k5BP0k3W3jZPUXO4rFXCCDm9eqMYUctkmoE0IbrAa4Ph
Hv/A+ujs+3etUQxK320u9v4IXncttMzRLIkVAgMBAAGjKTAnMBQGA1UdEQQNMAuC
CUIuaW52YWxpZDAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4GBADTP
BSezJqx9+7MZVqLcFz0K5K9NsVr5NRn8naC/W8mDNaSet4aeHLWZgVHwMZAiRka8
aAPYwoqXjjjS1/0Z/+eag24D81g2JvSk0t9dB44OCFfq2sgm1ERP0UW5BUKTf2iJ
WyOLpoMVFAeVqp4wug3IcWOOv8JAXmq9oAwlT92g
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIB0TCCATqgAwIBAgIEWVRCgjANBgkqhkiG9w0BAQsFADAUMRIwEAYDVQQDDAlC
LmludmFsaWQwHhcNMTcwNjI4MjM1NzU0WhcNMTgwNjI4MjM1NzU0WjAgMR4wHAYD
VQQDDBVzdGFja292ZXJmbG93LmludmFsaWQwgZ8wDQYJKoZIhvcNAQEBBQADgY0A
MIGJAoGBALh8r9s83H8zmW7QQvmLAVgHbDL6CmAGuePvshGgOu2s7IEiI5os36IH
PG4g1+UVf50U+osYRzXkq7F74fJlkMb1c4W3epn/SKOiL/HsEHVlo3EawX5OPgcC
8QopiNTPnhyOeEOm3lk5wldsBgw0g4MEwklfwaGD4rvCEFCeoVIVAgMBAAGjJDAi
MCAGA1UdEQQZMBeCFXN0YWNrb3ZlcmZsb3cuaW52YWxpZDANBgkqhkiG9w0BAQsF
AAOBgQBGj3dezNMMzE4PqkojXkenqKD6NlksldpRL3TOVAXCK6L0NciJbQcxi/9W
zfcaVQBGvNjmg6ieNYCamF+Fz/hg+m4pTrKLy54UnyOa8gUTg+tPJuJHO2FsdeOm
tbgQKLrqpBUJX4+SzEMQYzZfPhOj29SzItCDeRjYhn0m7Otp/Q==
-----END CERTIFICATE-----