Skip to content

Latest commit

 

History

67 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PyEndCrypt

用Python写的端到端加密工具,采用混合加密,实现了双棘轮的核心机制(注意不是完全实现)。 对数据进行双重校验,每条消息单独一个密钥。 使用简单,和平常使用socket套接字步骤差不多。

本项目适合想了解密码学的开发人员,提供有ECC和AES加解密供研究。如果你想,可以根据下文API进行二次开发。

项目目前仍处于开发阶段,如果你想参与开发请看下文工作清单

License: MIT


💡特点

  • 端到端加密,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 连接 ─────────────────────────> │
        │  <─── 关闭确认 ──────────────────────────────── │
        │                                                │
        │              连接关闭 ✅                         │


🔌API

NetworkBase

网络通信基类,包含数据发送和接收,以及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): 关闭连接

CryptoUntils

加密工具类,所有加密和解密,以及密钥生成均在这里实现
方法:

  • 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

加密客户端
方法:

  • 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

加密服务端
方法:

  • 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(): 关闭连接

CredentialProvisioner

证书密钥生成器
方法:

  • Generator(self, ca_cert: str, ca_key: str): 创建生成器
  • generate_cert(self, client_key): 生成客户端证书文件
  • generate_key(self): 生成客户端密钥文件

SSLBuilder

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()替换为日志记录系统(完成)
  • 添加服务端自动生成证书和密钥返回给客户端(完成)
  • 优化异常处理(完成)
  • 从内存中销毁密钥(完成)
  • 🟡 增加心跳机制
  • 🟡 实现异步
  • 🟡 实现处理多个客户端

⚠️免责声明

本项目仅用于学习和技术研究,严禁用于任何违法犯罪活动。 使用者必须遵守当地法律法规,并承担使用责任。 本项目开发者不承担因该项目引起的任何法律责任。

About

用Python写的端到端加密工具

Topics

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages