本文证书生成过程和https://www.yuque.com/ald/hrc57r/gelke1原理是一样的,但是更加简洁,只生成所需要的
生成证书
生成的证书:caroot.7z
参考:https://www.cnblogs.com/lsdb/p/9391979.html
至于windows如何安装openssl,前文讲过,请自行搜索
1、生成CA密钥及其自签名证书
# CA证书及密钥生成方法一----直接生成CA密钥及其自签名证书
# 如果想以后读取私钥文件ca_rsa_private.pem时不需要输入密码,亦即不对私钥进行加密存储,那么将-passout pass:123456替换成-nodes
openssl req -newkey rsa:2048 -passout pass:123456 -keyout ca_rsa_private.pem -x509 -days 365 -out ca.crt -subj "/C=CN/ST=GD/L=SZ/O=COM/OU=NSP/CN=CA/emailAddress=youremail@qq.com"
# CA证书及密钥生成方法二----分步生成CA密钥及其自签名证书:
# openssl genrsa -aes256 -passout pass:123456 -out ca_rsa_private.pem 2048
# openssl req -new -x509 -days 365 -key ca_rsa_private.pem -passin pass:123456 -out ca.crt -subj "/C=CN/ST=GD/L=SZ/O=COM/OU=NSP/CN=CA/emailAddress=youremail@qq.com"
2、生成服务器密钥及待签名证书
# 服务器证书及密钥生成方法一----直接生成服务器密钥及待签名证书
# 如果想以后读取私钥文件server_rsa_private.pem时不需要输入密码,亦即不对私钥进行加密存储,那么将-passout pass:server替换成-nodes
openssl req -newkey rsa:2048 -passout pass:server -keyout server_rsa_private.pem -out server.csr -subj "/C=CN/ST=GD/L=SZ/O=COM/OU=NSP/CN=SERVER/emailAddress=youremail@qq.com"
# 服务器证书及密钥生成方法二----分步生成服务器密钥及待签名证书
# openssl genrsa -aes256 -passout pass:server -out server_rsa_private.pem 2048
# openssl req -new -key server_rsa_private.pem -passin pass:server -out server.csr -subj "/C=CN/ST=GD/L=SZ/O=COM/OU=NSP/CN=SERVER/emailAddress=youremail@qq.com"
3、使用CA证书及密钥对服务器证书进行签名
# 使用CA证书及密钥对服务器证书进行签名:
openssl x509 -req -days 365 -in server.csr -CA ca.crt -CAkey ca_rsa_private.pem -passin pass:123456 -CAcreateserial -out server.crt
# 将加密的RSA密钥转成未加密的RSA密钥,避免每次读取都要求输入解密密码
# 密码就是生成私钥文件时设置的passout、读取私钥文件时要输入的passin,比如这里要输入“server”
openssl rsa -in server_rsa_private.pem -out server_rsa_private.pem.unsecure
4、直接生成客户端密钥及待签名证书
# 客户端证书及密钥生成方法一----直接生成客户端密钥及待签名证书
# 如果想以后读取私钥文件client_rsa_private.pem时不需要输入密码,亦即不对私钥进行加密存储,那么将-passout pass:client替换成-nodes
openssl req -newkey rsa:2048 -passout pass:client -keyout client_rsa_private.pem -out client.csr -subj "/C=CN/ST=GD/L=SZ/O=COM/OU=NSP/CN=CLIENT/emailAddress=youremail@qq.com"
# 客户端证书及密钥生成方法二----分步生成客户端密钥及待签名证书:
# openssl genrsa -aes256 -passout pass:client -out client_rsa_private.pem 2048
# openssl req -new -key client_rsa_private.pem -passin pass:client -out client.csr -subj "/C=CN/ST=GD/L=SZ/O=COM/OU=NSP/CN=CLIENT/emailAddress=youremail@qq.com"
5、使用CA证书及密钥对客户端证书进行签名
# 使用CA证书及密钥对客户端证书进行签名:
openssl x509 -req -days 365 -in client.csr -CA ca.crt -CAkey ca_rsa_private.pem -passin pass:123456 -CAcreateserial -out client.crt
# 将加密的RSA密钥转成未加密的RSA密钥,避免每次读取都要求输入解密密码
# 密码就是生成私钥文件时设置的passout、读取私钥文件时要输入的passin,比如这里要输入“client”
openssl rsa -in client_rsa_private.pem -out client_rsa_private.pem.unsecure
客户端
# encoding: utf8
# 表示当前的文件默认使用 gbk 编码
# 编码方式和解码方式要保持一致
# 导入套接字模块 socket
import socket
import threading
import ssl
# 接收数据的线程
def reciver_thread(ssock):
while True:
# 不断的打印接收到的数据
print(ssock.recv(100).decode())
# main 函数,为主模块时执行
def main():
# 生成SSL上下文
context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
# 加载信任根证书
context.load_verify_locations('cert/ca.crt')
# 与服务端建立socket连接
with socket.create_connection(('127.0.0.1', 9443)) as sock:
# 将socket打包成SSL socket,其主要工作是完成密钥协商
# 一定要注意的是这里的server_hostname不是指服务端IP,而是指服务端证书中设置的CN,我这里正好设置成127.0.1而已
with context.wrap_socket(sock, server_hostname='SERVER') as ssock:
threading.Thread(target=reciver_thread, args=(ssock,)).start()
# 向服务端发送信息
while True:
msg = input(">> ")
ssock.send(msg.encode("utf-8"))
if __name__ == "__main__":
main()
需要注意的是:
如果这个server_hostname没有写对,会造成以下错误
服务端
# encoding=utf-8
# 导入套接字模块 socket
import socket
import threading
import ssl
# 接收数据的线程
def reciver_thread(client_socket):
while True:
# 不断的打印接收到的数据
print(client_socket.recv(100).decode())
# main 函数,为主模块时执行
def main():
# 生成SSL上下文
context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
# 加载服务器所用证书和私钥
context.load_cert_chain('cert/server.crt', 'cert/server_rsa_private.pem.unsecure')
# 监听端口
with socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) as sock:
sock.bind(('127.0.0.1', 9443))
sock.listen(5)
# 将socket打包成SSL socket,其主要工作是完成密钥协商
with context.wrap_socket(sock, server_side=True) as ssock:
# 接收客户端连接
client_socket, addr = ssock.accept()
# 接收客户端信息
threading.Thread(target=reciver_thread, args=(client_socket,)).start()
# 向客户端发送信息
while True:
msg = input(">> ")
client_socket.send(msg)
if __name__ == "__main__":
main()