环境搭建
使用python3 来搭建demo, python相对c++ 实现功能很快。这里主要是讲下https 中 ssl/tls 的原理。 使用python 编写demo。
python3 安装需要的依赖
pip3 install flask
异常报错 timeout ,推荐使用
**pip --default-timeout=1688 install 库名称 -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com ** 进行安装
证书生成
#!/bin/bash
PROJECT_NAME="https Project"
# Generate the openssl configuration files.
cat > ca_cert.conf << EOF
[ req ]
distinguished_name = req_distinguished_name
prompt = no
[ req_distinguished_name ]
O = $PROJECT_NAME Certificate Authority
EOF
cat > server_cert.conf << EOF
[ req ]
distinguished_name = req_distinguished_name
prompt = no
[ req_distinguished_name ]
O = $PROJECT_NAME
CN = httpsServer
EOF
cat > client_cert.conf << EOF
[ req ]
distinguished_name = req_distinguished_name
prompt = no
[ req_distinguished_name ]
O = $PROJECT_NAME Device Certificate
CN = httpsClient
EOF
mkdir ca
mkdir server
mkdir client
# 生成私钥
openssl genrsa -out ca.key 1024
openssl genrsa -out server.key 1024
openssl genrsa -out client.key 1024
# 根据私钥创建证书请求文件,需要输入一些证书的元信息:邮箱、域名等
openssl req -out ca.req -key ca.key -new -config ./ca_cert.conf
openssl req -out server.req -key server.key -new -config ./server_cert.conf
openssl req -out client.req -key client.key -new -config ./client_cert.conf
# 结合私钥和请求文件,创建自签署证书, 此处建议使用二级证书来生成服务端和客户端证书
openssl x509 -req -in ca.req -out ca.crt -sha1 -days 5000 -signkey ca.key
openssl x509 -req -in server.req -out server.crt -sha1 -CAcreateserial -days 5000 -CA ca.crt -CAkey ca.key
openssl x509 -req -in client.req -out client.crt -sha1 -CAcreateserial -days 5000 -CA ca.crt -CAkey ca.key
mv ca.crt ca.key ca/
mv server.crt server.key server/
mv client.crt client.key client/
# rm *.conf
# rm *.req
# rm *.srl
需要先安装 openssl . 然后执行上面的脚本。
https 客户端 直接上代码
# 单项验证服务端证书
import urllib.request
import ssl
if __name__ == '__main__':
# 客户端认证服务端证书需要ca 此处单项认证服务端
CA_FILE = "caCert/ca/ca.crt"
# CA_FILE = "caCert/client/client.crt"
context = ssl.SSLContext(ssl.PROTOCOL_TLS)
context.check_hostname = False
context.load_verify_locations(CA_FILE)
context.verify_mode = ssl.CERT_REQUIRED
try:
request = urllib.request.Request('https://127.0.0.1:8091/login')
res = urllib.request.urlopen(request, context=context)
print(res.code)
print(res.read().decode("utf-8"))
except Exception as ex:
print("Found Error in auth phase:%s" % str(ex))
使用根证书验证签发的服务端证书
服务端验证客户端
from flask import Flask
import ssl
app = Flask(__name__)
# @app.route('/login')
# def hello_world():
# return 'Hello World!'
# if __name__ == '__main__':
# app.run(host="0.0.0.0", port=8091, ssl_context=('caCert/server/server.crt', 'caCert/server/server.key'))
# 方法改造 增加ssl 证书校验
@app.route('/login')
def hello_world():
return 'Hello World!'
# 配置ssl上下文,关键函数
def get_ssl_context():
# ca根证书
ca_crt_path = 'caCert/ca/ca.crt'
# 吊销列表
server_crl_path = ''
# 服务端证书和密钥
server_crt_path = 'caCert/server/server.crt'
server_key_path = 'caCert/server/server.key'
# server_crt_path = 'caCert/ca/ca.crt'
# server_key_path = 'caCert/ca/ca.key'
# 创建ssl上下文
ssl_context = ssl.SSLContext(protocol=ssl.PROTOCOL_TLSv1_2)
# 选择认证模式
# ssl_context.verify_mode = ssl.CERT_REQUIRED
ssl_context.verify_mode = ssl.CERT_NONE
# 不校验域名
ssl_context.check_hostname = False
# 吊销证书校验,只检查对端,不检查中间CA
# ssl_context.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF
# ssl_context.load_verify_locations(server_crl_path)
# 加密套件
ssl_context.set_ciphers = ("HIGH:!SSLv3:!TLSv1:!aNULL:@STRINGTH")
# 加载根证书
ssl_context.load_verify_locations(ca_crt_path)
# 加载服务端证书密钥,用于通信时使用
ssl_context.load_cert_chain(certfile=server_crt_path, keyfile=server_key_path)
return ssl_context
if __name__ == '__main__':
ssl_context = get_ssl_context()
app.run(host="0.0.0.0", port=8091, ssl_context=ssl_context)
细节可以参考:
https://www.cnblogs.com/Zzbj/p/15868210.html
https://blog.51cto.com/u_15127652/4590575
postman 验证测试
** 添加客户端证书**
完成: