自签SSL证书实现客户端登录认证

0.介绍

自己开发的使用了SSL协议的软件,通常没必要从证书签发机构那里来获取证书,自签证书成了必要的选择。自签证书还可以用来实现客户端登录认证。

1.创建CA

创建CA的私钥  openssl genrsa -des3 -out rootCA.key 4096  创建CA的自签证书  openssl req -x509 -new -nodes -sha256 -days 3650 -key rootCA.key -out rootCA.crt  

2.签发证书

生成证书的私钥  openssl genrsa -out server.key  4096  生成待签名的文件  openssl req -new -key server.key -out server.csr  使用CA进行签名  openssl x509 -req -CA rootCA.crt -CAKey  rootCA.key -CAcreateserial -days 365 -sha256 -in server.csr  -out server.crt  

这样就获取了经CA签发的私钥server.key和证书server.crt

3.客户端的登录认证

使用相同的CA来签发服务器证书和客户端证书,服务器就可以根据CA证书来鉴定客户端的是否具有登录权限。

即:凡是经过CA签发的证书,都能登录成功;否则失败  。

4.Python代码示例,演示如何验证客户端的证书

服务端代码:

 

import socket  from socket import AF_INET, SOCK_STREAM, SO_REUSEADDR, SOL_SOCKET, SHUT_RDWR  import ssl    listen_addr = '127.0.0.1'  listen_port = 8082  server_cert = 'server.crt'  server_key = 'server.key'  ca_cert = 'rootCA.crt'    context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH, cafile=ca_cert)  context.verify_mode = ssl.CERT_REQUIRED  context.load_cert_chain(certfile=server_cert, keyfile=server_key)  # context.load_verify_locations(cafile=ca_cert)    bindsocket = socket.socket()  bindsocket.bind((listen_addr, listen_port))  bindsocket.listen(5)    while True:      print("Waiting for client")      newsocket, fromaddr = bindsocket.accept()      print("Client connected: {}:{}".format(fromaddr[0], fromaddr[1]))      conn = context.wrap_socket(newsocket, server_side=True)      print("SSL established. Peer: {}".format(conn.getpeercert()))      buf = b''  # Buffer to hold received client data      try:          while True:              data = conn.recv(4096)              if data:                  # Client sent us data. Append to buffer                  buf += data              else:                  # No more data from client. Show buffer and close connection.                  print("Received:", buf)                  break      finally:          print("Closing connection")          conn.shutdown(socket.SHUT_RDWR)          conn.close()  

 

客户端代码

import socket  import ssl    host_addr = '127.0.0.1'  host_port = 8082  server_sni_hostname = 'example.com'  ca_cert = 'rootCA.crt'  client_cert = 'client.crt'  client_key = 'client.key'    context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH, cafile=ca_cert)  context.check_hostname = False  context.load_cert_chain(certfile=client_cert, keyfile=client_key)    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  conn = context.wrap_socket(s, server_side=False, server_hostname=server_sni_hostname)  conn.connect((host_addr, host_port))  print("SSL established. Peer: {}".format(conn.getpeercert()))  print("Sending: 'Hello, world!")  conn.send(b"Hello, world!")  print("Closing connection")  conn.close()  

  

参考