总结一下如何使用X.509证书来保护我们的设备的数据传输。
证书的签发
以下是证书签发的流程,为了更好的演示,我们需要分别创建两个根证书,并且用每个根证书来颁发一个客户端证书。这两个根证书分别为root_1.crt以及root_2.crt,对应的两个客户端证书分别为client_1.crt以及client_2.crt
- openssl genrsa -out rootkey.pem 2048
生成根证书的密匙 - openssl req -x509 -new -key rootkey.pem -out root.crt -subj="/C=CN/ST=GD/L=GZ/O=RootCA/OU=RootCA/CN=RootCA"
生成X509格式根证书 - openssl genrsa -out clientkey.pem 2048
生成客户端的密匙 - openssl req -new -key clientkey.pem -out client.csr -subj="/C=CN/ST=GD/L=GZ/O=BMW/OU=Vehicle/CN=Vehicle1"
生成客户端证书的请求文件,请求根证书来签发 - openssl x509 -req -in client.csr -CA root.crt -CAkey rootkey.pem -CAcreateserial -days 3650 -out client.crt
用根证书来签发客户端请求文件,生成客户端证书client.crt
证书的验证
验证客户端的证书是否是受信任的机构签发,例如以下的代码将验证client_1.crt是由root_1.crt签发,而client_2.crt不是由root_1.crt签发。
from OpenSSL.crypto import load_certificate, X509Store, X509StoreContext, X509StoreContextError
root_cert_1 = load_certificate(FILETYPE_PEM, open('root_1.crt').read())
root_cert_2 = load_certificate(FILETYPE_PEM, open('root_2.crt').read())
client_cert_1 = load_certificate(FILETYPE_PEM, open('client_1.crt').read())
client_cert_2 = load_certificate(FILETYPE_PEM, open('client_2.crt').read())
store_1 = X509Store()
store_1.add_cert(root_cert_1)
store_2 = X509Store()
store_2.add_cert(root_cert_2)
store_ctx = X509StoreContext(store_1, client_cert_1)
try:
if store_ctx.verify_certificate()==None:
print('Verify passed')
except X509StoreContextError:
print('Verfiy fail')
store_ctx = X509StoreContext(store_1, client_cert_2)
try:
if store_ctx.verify_certificate()==None:
print('Verify passed')
except X509StoreContextError:
print('Verfiy fail')
信息签名
有了证书之后,我们就可以用客户端的证书来对一段消息生成的摘要进行签名,这样可以确保消息没有被第三方篡改。
from cryptography import x509
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding
#Load the private key and sign the message digest
with open("clientkey_1.pem", "rb") as key_file:
private_key = serialization.load_pem_private_key(key_file.read(),password=None)
message = b"A message I want to sign"
signature = private_key.sign(
message,
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
),
hashes.SHA256()
)
#Load the public key from cert and verify the signature
client_cert_1 = x509.load_pem_x509_certificate(open('client_1.crt', 'rb').read())
public_key = client_cert_1.public_key()
public_key.verify(
signature,
message,
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
),
hashes.SHA256()
)