本文证书生成过程和https://www.yuque.com/ald/hrc57r/gelke1原理是一样的,但是更加简洁,只生成所需要的

生成证书

生成的证书:caroot.7z
参考:https://www.cnblogs.com/lsdb/p/9391979.html
至于windows如何安装openssl,前文讲过,请自行搜索

1、生成CA密钥及其自签名证书

  1. # CA证书及密钥生成方法一----直接生成CA密钥及其自签名证书
  2. # 如果想以后读取私钥文件ca_rsa_private.pem时不需要输入密码,亦即不对私钥进行加密存储,那么将-passout pass:123456替换成-nodes
  3. 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"
  4. # CA证书及密钥生成方法二----分步生成CA密钥及其自签名证书:
  5. # openssl genrsa -aes256 -passout pass:123456 -out ca_rsa_private.pem 2048
  6. # 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"

image.png

2、生成服务器密钥及待签名证书

  1. # 服务器证书及密钥生成方法一----直接生成服务器密钥及待签名证书
  2. # 如果想以后读取私钥文件server_rsa_private.pem时不需要输入密码,亦即不对私钥进行加密存储,那么将-passout pass:server替换成-nodes
  3. 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"
  4. # 服务器证书及密钥生成方法二----分步生成服务器密钥及待签名证书
  5. # openssl genrsa -aes256 -passout pass:server -out server_rsa_private.pem 2048
  6. # 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"

image.png

3、使用CA证书及密钥对服务器证书进行签名

  1. # 使用CA证书及密钥对服务器证书进行签名:
  2. openssl x509 -req -days 365 -in server.csr -CA ca.crt -CAkey ca_rsa_private.pem -passin pass:123456 -CAcreateserial -out server.crt
  3. # 将加密的RSA密钥转成未加密的RSA密钥,避免每次读取都要求输入解密密码
  4. # 密码就是生成私钥文件时设置的passout、读取私钥文件时要输入的passin,比如这里要输入“server”
  5. openssl rsa -in server_rsa_private.pem -out server_rsa_private.pem.unsecure

image.png
image.png

4、直接生成客户端密钥及待签名证书

  1. # 客户端证书及密钥生成方法一----直接生成客户端密钥及待签名证书
  2. # 如果想以后读取私钥文件client_rsa_private.pem时不需要输入密码,亦即不对私钥进行加密存储,那么将-passout pass:client替换成-nodes
  3. 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"
  4. # 客户端证书及密钥生成方法二----分步生成客户端密钥及待签名证书:
  5. # openssl genrsa -aes256 -passout pass:client -out client_rsa_private.pem 2048
  6. # 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"

image.png

5、使用CA证书及密钥对客户端证书进行签名

  1. # 使用CA证书及密钥对客户端证书进行签名:
  2. openssl x509 -req -days 365 -in client.csr -CA ca.crt -CAkey ca_rsa_private.pem -passin pass:123456 -CAcreateserial -out client.crt
  3. # 将加密的RSA密钥转成未加密的RSA密钥,避免每次读取都要求输入解密密码
  4. # 密码就是生成私钥文件时设置的passout、读取私钥文件时要输入的passin,比如这里要输入“client”
  5. openssl rsa -in client_rsa_private.pem -out client_rsa_private.pem.unsecure

image.png
image.png

客户端

  1. # encoding: utf8
  2. # 表示当前的文件默认使用 gbk 编码
  3. # 编码方式和解码方式要保持一致
  4. # 导入套接字模块 socket
  5. import socket
  6. import threading
  7. import ssl
  8. # 接收数据的线程
  9. def reciver_thread(ssock):
  10. while True:
  11. # 不断的打印接收到的数据
  12. print(ssock.recv(100).decode())
  13. # main 函数,为主模块时执行
  14. def main():
  15. # 生成SSL上下文
  16. context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
  17. # 加载信任根证书
  18. context.load_verify_locations('cert/ca.crt')
  19. # 与服务端建立socket连接
  20. with socket.create_connection(('127.0.0.1', 9443)) as sock:
  21. # 将socket打包成SSL socket,其主要工作是完成密钥协商
  22. # 一定要注意的是这里的server_hostname不是指服务端IP,而是指服务端证书中设置的CN,我这里正好设置成127.0.1而已
  23. with context.wrap_socket(sock, server_hostname='SERVER') as ssock:
  24. threading.Thread(target=reciver_thread, args=(ssock,)).start()
  25. # 向服务端发送信息
  26. while True:
  27. msg = input(">> ")
  28. ssock.send(msg.encode("utf-8"))
  29. if __name__ == "__main__":
  30. main()

需要注意的是:
image.png
如果这个server_hostname没有写对,会造成以下错误
image.png

服务端

  1. # encoding=utf-8
  2. # 导入套接字模块 socket
  3. import socket
  4. import threading
  5. import ssl
  6. # 接收数据的线程
  7. def reciver_thread(client_socket):
  8. while True:
  9. # 不断的打印接收到的数据
  10. print(client_socket.recv(100).decode())
  11. # main 函数,为主模块时执行
  12. def main():
  13. # 生成SSL上下文
  14. context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
  15. # 加载服务器所用证书和私钥
  16. context.load_cert_chain('cert/server.crt', 'cert/server_rsa_private.pem.unsecure')
  17. # 监听端口
  18. with socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) as sock:
  19. sock.bind(('127.0.0.1', 9443))
  20. sock.listen(5)
  21. # 将socket打包成SSL socket,其主要工作是完成密钥协商
  22. with context.wrap_socket(sock, server_side=True) as ssock:
  23. # 接收客户端连接
  24. client_socket, addr = ssock.accept()
  25. # 接收客户端信息
  26. threading.Thread(target=reciver_thread, args=(client_socket,)).start()
  27. # 向客户端发送信息
  28. while True:
  29. msg = input(">> ")
  30. client_socket.send(msg)
  31. if __name__ == "__main__":
  32. main()

效果

image.png
image.png