ubuntu下openssl签名证书制作流程及验证demo

1.创建根CA证书

生成 rootCA.key 以及 rootCA.crt. 用你的域名或者ip地址替换demo.mlopshub.com,比如192.168.10.11

openssl req -x509 \
            -sha256 -days 356 \
            -nodes \
            -newkey rsa:2048 \
            -subj "/CN=demo.mlopshub.com/C=CN/L=Beijing" \
            -keyout rootCA.key -out rootCA.crt 
或者
openssl req -x509 \
            -sha256 -days 356 \
            -nodes \
            -newkey rsa:2048 \
            -subj "/CN=192.168.10.11/C=CN/L=Beijing" \
            -keyout rootCA.key -out rootCA.crt 

如果上述命令提示Can't load /home/username/.rnd into RNG,则需要你手动创建这个文件

2. 生成自签名证书

2.1生成server的私有key

openssl genrsa -out server.key 2048

2.2.创建证书签名请求配置

根据实际情况替换域名以及IP

cat > csr.conf <<EOF
[ req ]
default_bits = 2048
prompt = no
default_md = sha256
req_extensions = req_ext
distinguished_name = dn

[ dn ]
C = US
ST = Beijing
L = Beijing
O = MLopsHub
OU = MlopsHub Dev
CN =test.com

[ req_ext ]
subjectAltName = @alt_names

[ alt_names ]
DNS.1 = test.com
DNS.2 = test2.com
IP.1 = 192.168.10.11
IP.2 = 192.168.1.22

EOF

2.3.使用服务器私钥生成证书签名请求(CSR)

openssl req -new -key server.key -out server.csr -config csr.conf

2.4.创建一个外部文件

根据实际情况替换域名以及IP

cat > cert.conf <<EOF

authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names

[alt_names]
DNS.1 = test.com
IP.1 = 192.168.10.62
EOF

2.5.使用自签名CA生成SSL证书

openssl x509 -req \
    -in server.csr \
    -CA rootCA.crt -CAkey rootCA.key \
    -CAcreateserial -out server.crt \
    -days 365 \
    -sha256 -extfile cert.conf

将server.crt server.key放到服务器目录下

将rootCA.crt放到客户端进行验签

3.python验证

3.1客户端单向/双向/不认证

(1)服务器端的代码

import socket
import ssl

# 服务器配置
SERVER_HOST = '192.168.10.62'
SERVER_PORT = 12345

def ssl_auth_double():
    # 创建一个普通的 TCP 套接字
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    print("Server socket created")

    # 绑定到本地地址和端口
    server_address = (SERVER_HOST, SERVER_PORT)
    server_socket.bind(server_address)
    print("Bound to address and port")

    # 开始监听连接
    server_socket.listen(1)
    print("Listening for connections")

    # 创建 SSL 上下文
    ssl_context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
    ssl_context.load_cert_chain(certfile="server.crt", keyfile="server.key")
    ssl_context.load_verify_locations(cafile="root_cli.crt")
    ssl_context.verify_mode = ssl.CERT_REQUIRED

    try:
        while True:
            # 接受客户端连接
            client_socket, client_address = server_socket.accept()
            print(f"Accepted connection from {client_address}")

            # 将客户端 socket 包装成 SSL socket
            ssl_socket = ssl_context.wrap_socket(client_socket, server_side=True)

            try:
                while True:
                    # 接收客户端数据
                    data = ssl_socket.recv(1024)
                    if not data:
                        break

                    # 将接收到的数据原样返回
                    ssl_socket.sendall(data)
            except socket.error as e:
                print(f"Socket error: {e}")
            finally:
                # 关闭 SSL socket
                ssl_socket.close()
    except KeyboardInterrupt:
        print("Server stopped by user")
    finally:
        # 关闭服务器 socket
        server_socket.close()

def ssl_auth_single():
    # 创建一个socket对象
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    print("Socket created")

    # 绑定到本地地址和端口
    server_address = (SERVER_HOST, SERVER_PORT)
    server_socket.bind(server_address)
    print("Bound to address and port")

    # 开始监听连接
    server_socket.listen(1)
    print("Listening for connections")

    # 创建SSL上下文
    ssl_context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
    ssl_context.load_cert_chain(certfile='server.crt', keyfile='server.key')
    print('Server is listening on {}:{}'.format(*server_address))
    while True:
        # 接受客户端连接
        client_socket, client_address = server_socket.accept()
        print('Accepted connection from {}:{}'.format(*client_address))

        # 将客户端socket包装成SSL socket
        ssl_socket = ssl_context.wrap_socket(client_socket, server_side=True)

        try:
            while True:
                # 接收客户端数据
                data = ssl_socket.recv(1024)
                if not data:
                    break

                # 将接收到的数据原样返回
                ssl_socket.sendall(data)
        except socket.error as e:
            print('Socket error:', e)
        finally:
            # 关闭SSL socket
            ssl_socket.close()

def ssl_only():
    # 创建一个普通的 TCP/IP 套接字
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_socket.bind((SERVER_HOST, SERVER_PORT))
    server_socket.listen(5)

    # 创建 SSL 上下文,禁用客户端证书验证
    context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
    context.load_cert_chain(certfile='server.crt', keyfile='server.key')
    context.verify_mode = ssl.CERT_NONE  # 不验证客户端证书

    # 将普通套接字封装为 SSL 套接字,开启 SSL 加密
    server_socket_ssl = context.wrap_socket(server_socket, server_side=True)

    print(f"Server is listening on {SERVER_HOST}:{SERVER_PORT}...")

    while True:
        # 等待客户端连接
        client_socket, addr = server_socket_ssl.accept()
        print(f"Connection from {addr} established!")

        try:
            # 接收数据
            data = client_socket.recv(1024)
            if data:
                print(f"Received: {data.decode('utf-8')}")
                # 将接收到的数据原样返回
                client_socket.sendall(data)
            else:
                print("No data received")
        except Exception as e:
            print(f"Error: {e}")
        finally:
            # 关闭客户端连接
            client_socket.close()
if __name__ == '__main__':
    ssl_only()

(2)客户端代码

import socket
import ssl
import os
import time
# 客户端配置
SERVER_HOST = '192.168.10.62'
SERVER_PORT = 12345
CA_CERT_FILE = 'rootCA.crt'  # CA 证书(客户端用于验证服务端)
current_directory = os.getcwd()
print(f"当前目录是: {current_directory}")

def ssl_auth_double():
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    print("Client socket created")

    # 创建 SSL 上下文
    ssl_context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH)
    ssl_context.load_cert_chain(certfile="client.crt", keyfile="client.key")
    ssl_context.load_verify_locations(cafile="rootCA.crt")
    ssl_context.verify_mode = ssl.CERT_REQUIRED

    # 将套接字包装为 SSL 套接字
    client_socket_ssl = ssl_context.wrap_socket(client_socket, server_hostname=SERVER_HOST)
    print("Client SSL socket wrapped")

    try:
        client_socket_ssl.connect((SERVER_HOST, SERVER_PORT))
        print(f"Connected to {SERVER_HOST}:{SERVER_PORT} over SSL.")

        while True:
            # 发送数据
            client_socket_ssl.sendall(b"Hello from SSL client!")
            print("Data sent to server")

            # 接收响应
            data = client_socket_ssl.recv(1024)
            print(f"Received from server: {data.decode('utf-8')}")
    except Exception as e:
        print(f"Error: {e}")
    finally:
        # 关闭连接
        client_socket_ssl.close()
def ssl_auth_single():
    # 创建一个普通的 TCP 套接字
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    print("Client socket created")

    # 将套接字包装为 SSL 套接字
    client_socket_ssl = ssl.wrap_socket(client_socket, certfile=None, keyfile=None, server_side=False, ssl_version=ssl.PROTOCOL_SSLv23, ca_certs=CA_CERT_FILE, cert_reqs=ssl.CERT_REQUIRED)
    print("Client SSL socket wrapped")

    try:
        client_socket_ssl.connect((SERVER_HOST, SERVER_PORT))
        print(f"Connected to {SERVER_HOST}:{SERVER_PORT} over SSL.")
        while True:
            # 发送数据
            client_socket_ssl.sendall(b"Hello from SSL client!")
            print("Data sent to server")

            # 接收响应
            data = client_socket_ssl.recv(1024)
            print(f"Received from server: {data.decode('utf-8')}")
            time.sleep(1)
    except Exception as e:
        print(f"Error: {e}")
    finally:
        # 关闭连接
        client_socket_ssl.close()
        print("Connection closed")
def ssl_only():
        # 创建一个普通的 TCP 套接字
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    print("Client socket created")

    # 创建 SSL 上下文
    ssl_context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH)
    ssl_context.check_hostname = False
    ssl_context.verify_mode = ssl.CERT_NONE
    # 设置支持的加密套件
    ssl_context.set_ciphers('ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA')

    # 将套接字包装为 SSL 套接字
    client_socket_ssl = ssl_context.wrap_socket(client_socket, server_hostname=SERVER_HOST)
    print("Client SSL socket wrapped")

    try:
        client_socket_ssl.connect((SERVER_HOST, SERVER_PORT))
        print(f"Connected to {SERVER_HOST}:{SERVER_PORT} over SSL.")
        
        while True:
            # 发送数据
            client_socket_ssl.sendall(b"Hello from SSL client!")
            print("Data sent to server")

            # 接收响应
            data = client_socket_ssl.recv(1024)
            print(f"Received from server: {data.decode('utf-8')}")
            time.sleep(1)
    except Exception as e:
        print(f"Error: {e}")
    finally:
        # 关闭连接
        client_socket_ssl.close()
        print("Connection closed")
if __name__ == '__main__':
    ssl_only()
相关推荐
sinat_3842410915 分钟前
使用 npm 安装 Electron 作为开发依赖
服务器
Kkooe2 小时前
GitLab|数据迁移
运维·服务器·git
虚拟网络工程师3 小时前
【网络系统管理】Centos7——配置主从mariadb服务器案例(下半部分)
运维·服务器·网络·数据库·mariadb
BLEACH-heiqiyihu3 小时前
RedHat7—Linux中kickstart自动安装脚本制作
linux·运维·服务器
勤奋的小王同学~4 小时前
项目虚拟机配置测试环境
服务器
007php0074 小时前
GoZero 上传文件File到阿里云 OSS 报错及优化方案
服务器·开发语言·数据库·python·阿里云·架构·golang
JosieBook4 小时前
【网络工程】查看自己电脑网络IP,检查网络是否连通
服务器·网络·tcp/ip
我的K84095 小时前
Flink整合Hudi及使用
linux·服务器·flink
1900435 小时前
linux6:常见命令介绍
linux·运维·服务器
Camellia-Echo5 小时前
【Linux从青铜到王者】Linux进程间通信(一)——待完善
linux·运维·服务器