本文证书生成过程和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替换成-nodesopenssl 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替换成-nodesopenssl 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替换成-nodesopenssl 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 编码# 编码方式和解码方式要保持一致# 导入套接字模块 socketimport socketimport threadingimport 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# 导入套接字模块 socketimport socketimport threadingimport 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()
效果


