openssl详解与应用教程
前言
SSL即安全套接字协议(Secure Sockets Layer),是为网络通信提供安全及数据完整性的一种安全协议。SSL在传输层与应用层之间对网络连接进行加密。
使用SSL有很多好处:认证用户和服务器,确保数据发送到正确的客户机和服务器;加密数据以防止数据中途被窃取;维护数据的完整性,确保数据在传输过程中不被改变。
作为一款优秀的产品,SSL功能是必不可少的。
1.概念
数字证书是一个经证书授权中心数字签名的包含公开**拥有者信息以及公开**的文件。
最简单的证书包含一个公开**、名称以及证书授权中心的数字签名。数字证书还有一个重要的特征就是只在特定的时间段内有效。数字证书是一种权威性的电子文档,可以由权威公正的第三方机构,即CA(例如中国各地方的CA公司)中心签发的证书,也可以由企业级CA系统进行签发。
一般证书分有三类,根证书、服务器证书和客户端证书。根证书,是生成服务器证书和客户端证书的基础,是信任的源头,也可以叫自签发证书,即CA证书。服务器证书,由根证书签发,配置在服务器上的证书。客户端证书,由根证书签发,配置在服务器上,并发送给客户,让客户安装在浏览器里的证书。
在了解SSL的时候可能会遇到很多名词概念,如
对称加密:例如平时给文件加密,加密和解密用的同一密码,即对称加密。
非对称加密:加密时用一个密码,而解锁时需要用另一个密码,即非对称加密。目前很流行的非对称加密算法是RSA算法,它是基于一个十分简单的数论事实:将两个大素数相乘十分容易,但是想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加***。
公钥:公钥是公开的,用来传输对方的随机**,只有通过私钥才能解密,这时就只有双方知道**了,从而达到安全传输的目的。
私钥:自己保留,只有通过私钥才能解密公钥加密的数据,对于私钥的使用可以设置密码。
2.通信过程
下面以最常见的单向认证为例,简述一下通信过程:
①客户端向服务器发送请求
②服务器将包含公钥的证书通过明文发送给客户端
③客户端通过根证书验证服务器证书是否有效
④如果有效,客户端生成一个随机**,也叫对称加***,使用服务器的公钥进行加密传输
⑤服务器通过私钥解密客户端传输的对称加***
⑥这时只有服务器和客户端知道这个对称加***,双方可以进行对称加密传输
3.通过openssl生成证书
通过openssl version -a
查看当前openssl的版本,一般的linux系统会自带SSL。
通过vim /usr/lib/ssl/openssl.cnf
修改配置文件,这里修改了默认文件夹、私钥名、证书名。
通过cd ssl
进入默认文件夹
在默认文件夹创建所需的目录和文件
mkdir -pv {certs,crl,newcerts,private}
touch {serial,index.txt,index.txt.attr}
-pv可以显示执行进度
指明证书开始的编号echo 01 >> serial
生成根证书私钥openssl genrsa -out private/ca.key 2048
genrsa --产生rsa**命令
-out —输出路径
这里的参数2048,指的是**的长度位数,默认长度为512位
生成自签名证书openssl req -new -x509 -key private/ca.key -out ca.crt -days 365
-new:表示生成一个新证书签署请求
-x509:专用于CA生成自签证书,如果不是自签证书则不需要此项
-key:用到的私钥文件
-out:证书的保存路径
-days:证书的有效期限,单位是day(天),默认是openssl.cnf的default_days
生成服务器**
openssl genrsa -out server.key 2048
生成请求文件,图中这几项需和根证书一致。
openssl req -new -key server.key -out server.csr
创建一个req文件夹,用于存放请求文件。mkdir req
颁发证书openssl ca -in req/server.csr -out certs/server.crt
4.通过Python编程验证
下面通过一个例程来模拟单向SSL认证,服务器需要准备好刚刚签发的服务器证书,和一定要好好保管的**,客户端只需准备好根证书就行,用来验证服务器的证书。
服务器代码
import socket
import ssl
class server_ssl:
def build_listen(self):
# 生成SSL上下文
context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
# 加载服务器所用证书和私钥
context.load_cert_chain('server.crt', 'server.key')
# 监听端口
with socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) as sock:
sock.bind(('0.0.0.0', 8888))
sock.listen(5)
# 将socket打包成SSL socket
with context.wrap_socket(sock, server_side=True) as ssock:
while True:
# 接收客户端连接
client_socket, addr = ssock.accept()
# 接收客户端信息
msg = client_socket.recv(1024).decode("utf-8")
print("receive msg from client {}:{}".format(addr, msg))
# 向客户端发送信息
msg = "yes , you have client_socketect with server.\r\n".encode("utf-8")
client_socket.send(msg)
client_socket.close()
if __name__ == "__main__":
server = server_ssl()
server.build_listen()
客户端代码
import socket
import ssl
class client_ssl:
def send_hello(self,):
# 生成SSL上下文
context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
# 加载信任根证书
context.load_verify_locations('ca.crt')
# 与服务端建立socket连接
with socket.create_connection(('0.0.0.0', 8888)) as sock:
# 将socket打包成SSL socket
# 一定要注意的是这里的server_hostname不是指服务端IP,而是指服务端证书中的CN。
with context.wrap_socket(sock, server_hostname='USER1') as ssock:
# 向服务端发送信息
msg = "do i connect with server ?".encode("utf-8")
ssock.send(msg)
# 接收服务端返回的信息
msg = ssock.recv(1024).decode("utf-8")
print("receive msg from server : {}".format(msg))
ssock.close()
if __name__ == "__main__":
client = client_ssl()
client.send_hello()
客户端运行结果
服务器运行结果
上一篇: Windows安装使用Openssl
下一篇: 尼姆博弈