用Python写的端到端加密工具,采用混合加密,实现了双棘轮的核心机制(注意不是完全实现)。 对数据进行双重校验,每条消息单独一个密钥。 使用简单,和平常使用socket套接字步骤差不多。
本项目适合想了解密码学的开发人员,提供有ECC和AES加解密供研究。如果你想,可以根据下文API进行二次开发。
项目目前仍处于开发阶段,如果你想参与开发请看下文工作清单
- 端到端加密,X25519 + AES 混合加密。
- 服务端和客户端强制加密,没有明文传输。
- 自动握手。
- 使用简单,代码简洁。
- 时间戳和消息序列号双重校验,防止重放攻击。
- 自动校验数据,保障安全性和完整性。
- 可以根据API自行进行拓展。
- 支持数据包大小伪造。
- 使用mTLS认证,保护服务端和客户端,杜绝中间人攻击。
- 采用TLS加密传输层,保障传输层安全。
- 支持动态客户端证书签发,客户端只需要 CA 证书即可。
- 消息密钥层级,会话根密钥 + 每条消息独立派生密钥。
- 自动密钥刷新,每5条消息自动更新根密钥,提供前向和后向安全性。
- 自动从内存中清理敏感数据。
警告: 由于 Python 语言的特性,并不能完全从内存中清理敏感数据,本项目采用的是转换 bytearray + gc 回收。
认证:mTLS
传输层:TLSv1.3
密钥交换阶段:ECC X25519 256位
密钥派生:HKDF-SHA256(会话根密钥 → 消息密钥)
数据加密:AES-GCM 256位
pip install cryptography服务端
from server import Server
crt = "" # 服务端证书路径
key = "" # 服务端密钥路径
ca_crt = "" # CA 证书路径
ca_key = "" # CA 密钥路径
padding = 0 # 数据包填充级别
server = Server("127.0.0.1",
5555,
crt,
key,
ca_crt,
ca_key,
padding)
server.accept()
server.send("Hello From Server")
data = server.receive()
print(data)
server.close()客户端
from client import Client
ca_crt = "" # CA 证书路径
client = Client("127.0.0.1",
5555,
ca_crt)
client.connect()
data = client.receive()
print(data)
client.send("Hello From Client")
client.close()关于各个证书和密钥,如果是测试环境,可以使用tools/generator.py一键生成。
通过设定padding参数开启数据包大小伪造,其原理是在密文末尾填充无意义垃圾数据,共两个级别:
数据包填充级别:
0:不填充
1:固定大小填充
2:随机大小填充
固定大小填充可以使数据包长度始终为128的倍数(由于使用TLSv1.3,实际大小会大一些)
随机大小填充可以使数据包增加一个随机长度,范围: 1~(256和剩余最大可用大小间的最小值)
┌──────────────────────────────────────────────────────────────────────────────┐
│ 应用层 (AES-GCM 加密前) │
├──────────┬──────────┬──────────────────────┬───────────────────────────────┤
│ 总长度头 │ 原始长度头│ 数据 │ 填充 │
│ 4 字节 │ 4 字节 │ 变长 │ 变长 │
├──────────┴──────────┴──────────────────────┴───────────────────────────────┤
│ AES-256-GCM 加密 │
├──────────┬──────────────────────────────────────────────┬───────────────────┤
│ Nonce │ 密文 │ Tag │
│ 12 字节 │ 变长 │ 16 字节 │
├──────────┴──────────────────────────────────────────────┴───────────────────┤
│ TLS 传输层封装 │
├──────────┬──────────┬──────────┬───────────────────────────────────────────┤
│ TLS类型 │ TLS版本 │ TLS长度 │ TLS加密数据 │
│ 1 字节 │ 2 字节 │ 2 字节 │ 变长 │
└──────────┴──────────┴──────────┴───────────────────────────────────────────┘
╔═══════════════════════════════════════════════════════════════════════════════╗
║ PyEndCrypt 完整通信流程(一条消息) ║
╚═══════════════════════════════════════════════════════════════════════════════╝
┌───────────────────────────────────────────────────────────────────────────────┐
│ 阶段1: TCP 连接建立 (普通连接,用于证书分发) │
└───────────────────────────────────────────────────────────────────────────────┘
Client(5555) Server(5555)
│ │
│ ──── SYN ────────────────────────────────────> │
│ <─── SYN-ACK ───────────────────────────────── │
│ ──── ACK ────────────────────────────────────> │
│ │
│ TCP 连接建立 ✅ │
┌───────────────────────────────────────────────────────────────────────────────┐
│ 阶段2: 协商 (Negotiation) │
└───────────────────────────────────────────────────────────────────────────────┘
│ │
│ <─── encoding="utf-8" ──────────────────────── │
│ <─── padding=0 ─────────────────────────────── │
│ ──── "OK" ───────────────────────────────────> │
│ │
│ 协商完成 ✅ │
┌───────────────────────────────────────────────────────────────────────────────┐
│ 阶段3: 第一次加密握手 (X25519 密钥交换) │
└───────────────────────────────────────────────────────────────────────────────┘
│ │
│ ──── ClientHello ─────────────────────────────> │
│ │
│ ┌──────────────────────────────────────────┐ │
│ │ 生成临时密钥对 (privC1, pubC1) │ │
│ │ privC1 = X25519PrivateKey.generate() │ │
│ │ pubC1 = privC1.public_key() │ │
│ └──────────────────────────────────────────┘ │
│ │
│ ──── pubC1 (32 bytes) ──────────────────────> │
│ │ ┌─────────────────┐
│ │ │ 生成临时密钥对 │
│ │ │ (privS1, pubS1) │
│ <─── pubS1 (32 bytes) ─────────────────────── │ └─────────────────┘
│ │
│ ┌──────────────────────────────────────────┐ │ ┌─────────────────┐
│ │ 计算共享密钥 │ │ │ 计算共享密钥 │
│ │ shared1 = DH(privC1, pubS1) │ │ │ shared1 = DH(privS1, pubC1) │
│ │ root_key1 = KDF(shared1, "session") │ │ │ root_key1 = KDF(shared1, "session") │
│ └──────────────────────────────────────────┘ │ └─────────────────┘
│ │
│ ──── "Client Hello" ──────────────────────────> │
│ <─── "Server Hello" ─────────────────────────── │
│ │
│ 第一次握手完成 ✅ 根密钥: root_key1 │
┌───────────────────────────────────────────────────────────────────────────────┐
│ 阶段4: 证书分发 (使用 root_key1 加密) │
└───────────────────────────────────────────────────────────────────────────────┘
│ │
│ ┌──────────────────────────────────────────┐ │ ┌─────────────────┐
│ │ 生成客户端证书和密钥 │ │ │ 生成客户端证书 │
│ │ (通过 OpenSSL 动态生成) │ │ │ 和密钥 │
│ └──────────────────────────────────────────┘ │ └─────────────────┘
│ │
│ ┌──────────────────────────────────────────┐ │
│ │ 加密证书 │ │
│ │ message_key = HKDF(root_key1, seq=1) │ │
│ │ ciphertext = AES-GCM(message_key, key) │ │
│ └──────────────────────────────────────────┘ │
│ │
│ <─── 加密的 client.key (seq=1) ─────────────── │
│ │
│ ┌──────────────────────────────────────────┐ │
│ │ 解密证书 │ │
│ │ message_key = HKDF(root_key1, seq=1) │ │
│ │ client_key = AES-GCM(message_key) │ │
│ └──────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────┐ │
│ │ 加密证书 │ │
│ │ message_key = HKDF(root_key1, seq=2) │ │
│ │ ciphertext = AES-GCM(message_key, crt) │ │
│ └──────────────────────────────────────────┘ │
│ │
│ <─── 加密的 client.crt (seq=2) ─────────────── │
│ │
│ ┌──────────────────────────────────────────┐ │
│ │ 解密证书 │ │
│ │ message_key = HKDF(root_key1, seq=2) │ │
│ │ client_crt = AES-GCM(message_key) │ │
│ └──────────────────────────────────────────┘ │
│ │
│ 证书分发完成 ✅ │
│ │
│ 关闭普通 TCP 连接 │
│ ──── FIN ────────────────────────────────────> │
│ <─── ACK ───────────────────────────────────── │
┌───────────────────────────────────────────────────────────────────────────────┐
│ 阶段5: SSL/TLS 连接建立 (mTLS 双向认证) │
└───────────────────────────────────────────────────────────────────────────────┘
│ │
│ ┌──────────────────────────────────────────┐ │
│ │ 使用刚收到的客户端证书 │ │
│ │ client.crt + client.key │ │
│ └──────────────────────────────────────────┘ │
│ │
│ ──── TCP 连接 (新连接) ─────────────────────> │
│ │
│ ┌──────────────────────────────────────────┐ │
│ │ SSL/TLS 握手 (mTLS) │ │
│ │ - 双向证书验证 │ │
│ │ - TLS 1.3 加密通道 │ │
│ └──────────────────────────────────────────┘ │
│ │
│ <─── SSL/TLS 加密通道建立 ✅ ───────────────── │
│ │
│ TLS 加密通道 (传输层) │
┌───────────────────────────────────────────────────────────────────────────────┐
│ 阶段6: 第二次加密握手 (新的 X25519 密钥交换) │
└───────────────────────────────────────────────────────────────────────────────┘
│ │
│ ┌──────────────────────────────────────────┐ │ ┌─────────────────┐
│ │ 生成临时密钥对 (privC2, pubC2) │ │ │ 生成临时密钥对 │
│ └──────────────────────────────────────────┘ │ │ (privS2, pubS2) │
│ │ └─────────────────┘
│ ──── pubC2 (32 bytes) ──────────────────────> │
│ <─── pubS2 (32 bytes) ─────────────────────── │
│ │
│ ┌──────────────────────────────────────────┐ │ ┌─────────────────┐
│ │ 计算共享密钥 │ │ │ 计算共享密钥 │
│ │ shared2 = DH(privC2, pubS2) │ │ │ shared2 = DH(privS2, pubC2) │
│ │ root_key2 = KDF(shared2, "session") │ │ │ root_key2 = KDF(shared2, "session") │
│ └──────────────────────────────────────────┘ │ └─────────────────┘
│ │
│ ──── "Client Hello" ──────────────────────────> │
│ <─── "Server Hello" ─────────────────────────── │
│ │
│ 第二次握手完成 ✅ 根密钥: root_key2 │
┌───────────────────────────────────────────────────────────────────────────────┐
│ 阶段7: 业务消息传输 (一条消息) │
└───────────────────────────────────────────────────────────────────────────────┘
│ │
│ ┌──────────────────────────────────────────┐ │
│ │ 客户端发送消息 │ │
│ │ message_key = HKDF(root_key2, seq=3) │ │
│ │ ciphertext = AES-GCM(message_key, │ │
│ │ "Hello Server") │ │
│ └──────────────────────────────────────────┘ │
│ │
│ ──── 加密数据 (seq=3) ──────────────────────> │
│ │
│ ┌──────────────────────────────────────────┐
│ │ 服务端接收消息 │
│ │ shared = DH(privS2, pubC2) │
│ │ root_key2 = KDF(shared, "session") │
│ │ message_key = HKDF(root_key2, seq=3) │
│ │ "Hello Server" = AES-GCM(message_key) │
│ └──────────────────────────────────────────┘
│ │
│ ┌──────────────────────────────────────────┐ │
│ │ 服务端回复消息 │ │
│ │ message_key = HKDF(root_key2, seq=4) │ │
│ │ ciphertext = AES-GCM(message_key, │ │
│ │ "Hello Client") │ │
│ └──────────────────────────────────────────┘ │
│ │
│ <─── 加密数据 (seq=4) ──────────────────────── │
│ │
│ ┌──────────────────────────────────────────┐ │
│ │ 客户端接收回复 │ │
│ │ message_key = HKDF(root_key2, seq=4) │ │
│ │ "Hello Client" = AES-GCM(message_key) │ │
│ └──────────────────────────────────────────┘ │
│ │
│ 消息传输完成 ✅ │
┌───────────────────────────────────────────────────────────────────────────────┐
│ 阶段8: 连接关闭 │
└───────────────────────────────────────────────────────────────────────────────┘
│ ──── 关闭 TLS 连接 ─────────────────────────> │
│ <─── 关闭确认 ──────────────────────────────── │
│ │
│ 连接关闭 ✅ │
网络通信基类,包含数据发送和接收,以及socket套接字的关闭处理
方法:
_recv_exact(self, n: int): 精确接收n个字节数据_send_raw(self, data): 发送原始数据包_recv_raw(self): 接收原始数据包_add_padding(self, data: bytes): 填充数据_remove_padding(self, data: bytes): 移除填充的数据close(self): 关闭连接
加密工具类,所有加密和解密,以及密钥生成均在这里实现
方法:
generate_keypair(): 生成临时密钥对init_session(peer_public_key): 初始化会话,生成根密钥refresh_session(peer_public_key): 刷新会话根密钥derive_message_key(seq): 从根密钥派生消息密钥derive_shared_key(private_key: X25519PrivateKey, peer_public_bytes: bytes): 用 X25519 密钥派生出共享密钥shared_key_derive_aes_key(shared_key: bytes, salt: bytes): 从共享密钥中派生出 AES 密钥_pack(data: bytes, seq: int): 将8字节时间戳和4字节序列号打包进数据中_unpack(data: bytes): 解包数据_verify(timestamp: int, seq: int, data_seq: int, window=TIMEOUT): 数据校验aes_encrypt(peer_public_key: bytes, data: bytes, seq: int): 使用 AES 私钥加密数据aes_decrypt(data: bytes, seq: int, private_key: X25519PrivateKey): 使用 AES 私钥解密数据clear_session(): 清除会话密钥
加密客户端
方法:
Client(self, host: str, port: int, ca_cert: str, padding: int = 0, encoding: str = "utf-8"): 创建客户端_negotiate(): 预先协商_handshake(): 建立加密握手_refresh_keypair(): 重新交换密钥connect(): 连接服务器并完成握手send(data): 加密数据并发送receive(): 接收数据并解密close(): 关闭连接
加密服务端
方法:
Server(self, host: str, port: int, listen: int, server_cert: str, server_key: str, ca_cert:str, ca_key: str, padding: int = 0, encoding: str = "utf-8"): 创建服务端_negotiate(): 预先协商_handshake(): 建立加密握手_refresh_keypair(): 重新交换密钥accept(): 接受连接并完成握手send(data): 加密数据并发送receive(): 接收数据并解密close(): 关闭连接
证书密钥生成器
方法:
Generator(self, ca_cert: str, ca_key: str): 创建生成器generate_cert(self, client_key): 生成客户端证书文件generate_key(self): 生成客户端密钥文件
SSL 连接构建器
方法:
Builder(self, cert: str, key: str, ca_cert: str, is_server): 创建构建器
PyEndCrypt/
├── README.md # 自述文件
├── LICENSE # 开源许可证
├── server.py # 加密服务端
├── client.py # 加密客户端
└── tools
├── CryptoUtils.py # 加密工具类
├── Logger.py # 日志记录器
├── NetworkBase.py # 网络通信基类
├── CredentialProvisioner.py # 客户端证书和密钥生成器
├── SSLBuilder.py # SSL 连接构建器
├── generator.py # 证书密钥全生成器
├── exceptions.py # 所有异常的基类
├── secure_memory.py # 内存清理工具
└── __init__.py
如果你想参与开发,可以依据这个清单改进(颜色代表优先级)
- ⚫
实现服务器公钥指纹验证(已由TLS和mTLS替代) - ⚫
添加客户端身份验证(已由TLS和mTLS替代) - ⚫
将(完成)print()替换为日志记录系统 - ⚫
添加服务端自动生成证书和密钥返回给客户端(完成) - ⚫
优化异常处理(完成) - ⚫
从内存中销毁密钥(完成) - 🟡 增加心跳机制
- 🟡 实现异步
- 🟡 实现处理多个客户端
本项目仅用于学习和技术研究,严禁用于任何违法犯罪活动。 使用者必须遵守当地法律法规,并承担使用责任。 本项目开发者不承担因该项目引起的任何法律责任。