欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

openssl详解与应用教程

程序员文章站 2022-06-29 21:11:40
...

前言

SSL即安全套接字协议(Secure Sockets Layer),是为网络通信提供安全及数据完整性的一种安全协议。SSL在传输层与应用层之间对网络连接进行加密。

使用SSL有很多好处:认证用户和服务器,确保数据发送到正确的客户机和服务器;加密数据以防止数据中途被窃取;维护数据的完整性,确保数据在传输过程中不被改变。
作为一款优秀的产品,SSL功能是必不可少的。

1.概念

数字证书是一个经证书授权中心数字签名的包含公开**拥有者信息以及公开**的文件。

最简单的证书包含一个公开**、名称以及证书授权中心的数字签名。数字证书还有一个重要的特征就是只在特定的时间段内有效。数字证书是一种权威性的电子文档,可以由权威公正的第三方机构,即CA(例如中国各地方的CA公司)中心签发的证书,也可以由企业级CA系统进行签发。

一般证书分有三类,根证书服务器证书客户端证书。根证书,是生成服务器证书和客户端证书的基础,是信任的源头,也可以叫自签发证书,即CA证书。服务器证书,由根证书签发,配置在服务器上的证书。客户端证书,由根证书签发,配置在服务器上,并发送给客户,让客户安装在浏览器里的证书。

在了解SSL的时候可能会遇到很多名词概念,如
对称加密:例如平时给文件加密,加密和解密用的同一密码,即对称加密。

非对称加密:加密时用一个密码,而解锁时需要用另一个密码,即非对称加密。目前很流行的非对称加密算法是RSA算法,它是基于一个十分简单的数论事实:将两个大素数相乘十分容易,但是想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加***。

公钥:公钥是公开的,用来传输对方的随机**,只有通过私钥才能解密,这时就只有双方知道**了,从而达到安全传输的目的。

私钥:自己保留,只有通过私钥才能解密公钥加密的数据,对于私钥的使用可以设置密码。

2.通信过程

下面以最常见的单向认证为例,简述一下通信过程:

①客户端向服务器发送请求

②服务器将包含公钥的证书通过明文发送给客户端

③客户端通过根证书验证服务器证书是否有效

④如果有效,客户端生成一个随机**,也叫对称加***,使用服务器的公钥进行加密传输

⑤服务器通过私钥解密客户端传输的对称加***

⑥这时只有服务器和客户端知道这个对称加***,双方可以进行对称加密传输
openssl详解与应用教程

3.通过openssl生成证书

通过openssl version -a查看当前openssl的版本,一般的linux系统会自带SSL。
openssl详解与应用教程

通过vim /usr/lib/ssl/openssl.cnf修改配置文件,这里修改了默认文件夹、私钥名、证书名。
openssl详解与应用教程
通过cd ssl进入默认文件夹
openssl详解与应用教程
在默认文件夹创建所需的目录和文件

mkdir -pv {certs,crl,newcerts,private}
touch {serial,index.txt,index.txt.attr}
-pv可以显示执行进度
openssl详解与应用教程

指明证书开始的编号
echo 01 >> serial
openssl详解与应用教程

生成根证书私钥
openssl genrsa -out private/ca.key 2048

genrsa --产生rsa**命令

-out —输出路径

这里的参数2048,指的是**的长度位数,默认长度为512位
openssl详解与应用教程

生成自签名证书
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详解与应用教程

生成服务器**

openssl genrsa -out server.key 2048

openssl详解与应用教程

生成请求文件,图中这几项需和根证书一致。

openssl req -new -key server.key -out server.csr
openssl详解与应用教程

创建一个req文件夹,用于存放请求文件。
mkdir req

颁发证书
openssl ca -in req/server.csr -out certs/server.crt
openssl详解与应用教程

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()

客户端运行结果
openssl详解与应用教程
服务器运行结果
openssl详解与应用教程