4 Commits
Author SHA1 Message Date
dvs bad851f741 更新 chaoscrypt.py 2026-08-28 00:55:02 +00:00
dvs b311483963 更新 README.md 2026-08-28 00:53:38 +00:00
dvs ef90efd199 revert 587ef2140b
revert 删除 .gitignore
2026-08-28 00:51:40 +00:00
dvs 587ef2140b 删除 .gitignore 2026-08-27 10:46:24 +00:00
2 changed files with 618 additions and 504 deletions
+275 -273
View File
@@ -1,345 +1,347 @@
# 🔐 ChaosCrypt - 混沌加密系统(v2.0)
**一个完全自主设计的、抗量子、抗数学攻击的对称加密系统**
# 🔐 ChaosCrypt - Chaos Encryption System (v2.0)
*不依赖 NIST、不依赖椭圆曲线、不依赖质数分解——只依赖随机性本身*
**A fully self-designed, quantum-resistant, math-attack-resistant symmetric encryption system**
**v2.0 新增 💬 ChaosCryptChat:基于混沌加密的端到端加密聊天系统(文本/图片/文件/语音)**
*No NIST, no elliptic curves, no prime factorization—only randomness itself*
**v2.0 New Addition 💬 ChaosCryptChat: End-to-end encrypted chat system (text/images/files/voice) built on ChaosCrypt**
---
## 📖 目录
## 📖 Table of Contents
1. [项目简介](#项目简介)
2. [设计哲学](#设计哲学)
3. [核心特性](#核心特性)
4. [加密流程详解](#加密流程详解)
5. [安全性分析](#安全性分析)
6. [为什么这玩意儿真的安全?(不服来辩版)](#为什么这玩意儿真的安全不服来辩版)
7. [快速开始](#快速开始)
8. [使用指南](#使用指南)
9. [API 参考](#api-参考)
10. [常见问题](#常见问题)
11. [💬 ChaosCryptChat 混沌加密聊天](#-chaoscryptchat-混沌加密聊天)
12. [项目结构](#项目结构)
13. [免责声明](#免责声明)
1. [Project Overview](#project-overview)
2. [Design Philosophy](#design-philosophy)
3. [Core Features](#core-features)
4. [Encryption Workflow](#encryption-workflow)
5. [Security Analysis](#security-analysis)
6. [Why This Is Actually Secure (No-BS Edition)](#why-this-is-actually-secure-no-bs-edition)
7. [Quick Start](#quick-start)
8. [Usage Guide](#usage-guide)
9. [API Reference](#api-reference)
10. [FAQ](#faq)
11. [💬 ChaosCryptChat](#-chaoscryptchat-chaos-encrypted-chat)
12. [Project Structure](#project-structure)
13. [Disclaimer](#disclaimer)
---
## 项目简介
## Project Overview
**ChaosCrypt** 是一个完全自主设计的对称加密系统。它不依赖任何第三方加密库(仅使用 `base64` 做数据编码),全部加密逻辑均为原创。
**ChaosCrypt** is a fully self-designed symmetric encryption system. It relies on no third-party crypto libraries (only `base64` for encoding)—all encryption logic is original.
**核心思想**:用**随机性**替代**数学结构**,用**多层乱序**替代**代数方程**,用**超大密钥空间**彻底扼杀暴力破解。
**Core idea**: Replace **mathematical structure** with **randomness**, replace **algebraic equations** with **multi-layer obfuscation**, and use an **immense key space** to completely shut down brute force.
> 这不是对现有加密算法的改进,而是对"安全"这个概念的重新定义。
> This is not an improvement on existing algorithms—it's a redefinition of what "secure" means.
**v2.0 新增**:在混沌加密内核之上构建了 **ChaosCryptChat** 端到端加密聊天系统,让混沌加密真正走进实时通信场景。
**v2.0 New**: Built **ChaosCryptChat**, an end-to-end encrypted chat system on top of the ChaosCrypt kernel, bringing chaos encryption to real-time communication.
---
## 设计哲学
## Design Philosophy
当今加密世界有一个默认共识:**"只有 NIST 认证的、数学优美的、学术界验证过的算法才算安全"**。
There's a consensus in the crypto world: *"Only NIST-certified, mathematically elegant, academically vetted algorithms are secure."*
ChaosCrypt 对此表示:
ChaosCrypt says:
> **"你们说的都对,但我不信。"**
> **"You're not wrong, but I don't buy it."**
- **Dual_EC_DRBG** 事件还历历在目——NIST 标准,NSA 后门,全世界被蒙在鼓里好几年。
- **RSA** 数学优美吧?标准吧?**Shor 一来直接秒死。**
- **AES** 结构清晰吧?S-Box 有理有据吧?**Grover 直接给你开根号加速。**
- **Dual_EC_DRBG** is still fresh—NIST standard, NSA backdoor, the whole world fooled for years.
- **RSA** is mathematically beautiful, right? Standard, right? **Shor kills it instantly.**
- **AES** has a clean structure, a well-reasoned S-Box, right? **Grover gives you a square-root speedup.**
**ChaosCrypt 选择另一条路:**
**ChaosCrypt takes another path:**
> **不要数学结构,不要可解释性,不要任何人给你背书。**
> **你唯一能做的只有暴力枚举——而枚举空间大到宇宙都装不下。**
> **No math structure. No explainability. No one's stamp of approval.**
> **Your only move is brute force—and the space is so large the universe can't hold it.**
---
## 核心特性
## Core Features
| 特性 | 说明 |
|------|------|
| 🔑 **双因素保护** | 系统密钥文件 (`.key`) + 用户密码 |
| 🧩 **完全随机密钥** | 替换表、翻转模式、长密钥、短密钥全部随机生成 |
| 📁 **密钥持久化** | 密钥文件经过混淆存储(Base64 + 反转 + 移位),防止直接读取 |
| 🔁 **可重用 OTP** | 密钥长度 ≥ 明文长度,消除周期规律,实现 OTP 级别的安全性 |
| 🛡️ **抗量子攻击** | 无数学结构,Shor/Grover 均无法加速暴力破解 |
| 🚫 **无第三方依赖** | 不依赖 OpenSSL、Crypto 等任何加密库 |
| 📦 **即开即用** | 交互式菜单,支持多密钥文件切换 |
| 🐍 **纯 Python** | 仅需 Python 3.6+,零额外依赖 |
| 💬 **加密聊天(v2.0)** | ChaosCryptChat 端到端加密聊天:文本/图片/文件/语音,P2P + 中央服务器双模式 |
| Feature | Description |
|---------|-------------|
| 🔑 **Two-factor protection** | System key file (`.key`) + user password |
| 🧩 **Fully random keys** | Substitution tables, flip patterns, long key, short key all randomly generated |
| 📁 **Key persistence** | Keys stored obfuscated (Base64 + reversal + shift) to prevent casual reading |
| 🔁 **Reusable OTP** | Key length ≥ plaintext length, eliminating periodic patterns—OTP-level security |
| 🛡️ **Quantum-resistant** | No math structure, so Shor/Grover can't speed up brute force |
| 🚫 **Zero third-party deps** | No OpenSSL, no Crypto, no nothing |
| 📦 **Ready to use** | Interactive menu, multiple key file support |
| 🐍 **Pure Python** | Just Python 3.6+, no extra dependencies |
| 💬 **Encrypted Chat (v2.0)** | ChaosCryptChat: E2E text/images/files/voice, P2P + central server modes |
---
## 加密流程详解
## Encryption Workflow
```
明文
Plaintext
↓
① Base64 编码
① Base64 encode
↓
② 随机替换表(大小写各26字母完全打乱)
② Random substitution (26 uppercase + 26 lowercase fully shuffled)
↓
③ 大小写翻转(10位随机模式)
③ Case flip (10‑bit random pattern)
↓
④ 字符串反转
④ String reversal
↓
⑤ 动态异或(4096位长密钥)
⑤ Dynamic XOR (4096‑bit long key)
↓
⑥ 最终异或(用户密码 + 512位短密钥 派生)
⑥ Final XOR (user password + 512‑bit short key derived)
↓
密文(十六进制)
Ciphertext (hex)
```
每一步使用的随机参数都来自 `.key` 文件,用户密码仅参与最后一步的密钥派生。
Every random parameter comes from the `.key` file. The user password is only used in the final key derivation step.
### 密钥派生流程
### Key Derivation Flow
```
用户密码 + short_key (512位)
User password + short_key (512 bits)
↓
交替穿插 → 位运算混合 → 分组置换 → 反转
Interleave → bitwise mixing → block permutation → reversal
↓
扩展至目标长度(三种变换模式循环)
Expand to target length (three transformation modes cycled)
↓
最终密钥(长度 >= 明文)
Final key (length ≥ plaintext)
```
---
## 安全性分析
## Security Analysis
### 1. 无法建立数学方程
### 1. No Mathematical Equations to Write
| 传统算法 | 方程形式 | 攻击方式 |
|----------|----------|----------|
| RSA | c = m^e mod n | 数域筛法、Shor |
| AES | State = SBox ∘ ShiftRow ∘ MixCol ∘ AddRoundKey | 差分分析、Grover |
| ECC | Q = kP | 离散对数、Shor |
| **ChaosCrypt** | **无法写出任何有意义的方程** | **只能暴力枚举** |
| Traditional Alg | Equation Form | Attack Vector |
|-----------------|---------------|---------------|
| RSA | c = m^e mod n | Number field sieve, Shor |
| AES | State = SBox ∘ ShiftRow ∘ MixCol ∘ AddRoundKey | Differential, Grover |
| ECC | Q = kP | Discrete log, Shor |
| **ChaosCrypt** | **No meaningful equation can be written** | **Brute force only** |
> 原因:替换表是查表操作,翻转模式是硬编码数组,密钥派生是黑盒混合——每一步都是"随机查表",没有可解析的代数结构。
> Why: substitution is table lookup, flip pattern is a hardcoded array, key derivation is a black-box mix—every step is "random table lookup" with no parseable algebraic structure.
### 2. 密钥空间(暴力破解难度)
### 2. Key Space (Brute‑Force Difficulty)
| 组件 | 空间大小 | 数值 |
|------|----------|------|
| Component | Space Size | Approx. Value |
|-----------|------------|---------------|
| `upper_mapping` | 26! | ~10²⁶ |
| `lower_mapping` | 26! | ~10²⁶ |
| `digit_mapping` | ~10! × C(62,10) | ~10¹⁴ |
| `equal_mapping` | 62×61×60×59 | ~10⁷ |
| `long_key` (4096位hex) | 16⁴⁰⁹⁶ | ~10⁴⁹³² |
| `short_key` (512位hex) | 16⁵¹² | ~10⁶¹⁶ |
| `long_key` (4096‑bit hex) | 16⁴⁰⁹⁶ | ~10⁴⁹³² |
| `short_key` (512‑bit hex) | 16⁵¹² | ~10⁶¹⁶ |
| `flip_pattern` | 2¹⁰ | ~10³ |
| 用户密码(最低8位) | ~10⁸ | |
| User password (min 8 chars) | ~10⁸ | |
**总搜索空间 ≈ 10⁵⁶³²**
**Total search space ≈ 10⁵⁶³²**
**对比数据**:
**Comparisons**:
- 宇宙原子总数:≈ 10⁸⁰
- AES-256 密钥空间:≈ 10⁷⁷
- RSA-2048 密钥空间:≈ 10⁶¹⁶
- **ChaosCrypt:≈ 10⁵⁶³²**(是 AES 的 10⁵⁵⁵⁵ 倍)
- Atoms in the observable universe: ≈ 10⁸⁰
- AES‑256 key space: ≈ 10⁷⁷
- RSA‑2048 key space: ≈ 10⁶¹⁶
- **ChaosCrypt: ≈ 10⁵⁶³²** (10⁵⁵⁵⁵ × AES)
> **即使全宇宙原子都变成量子计算机,也无法在宇宙生命周期内枚举完。**
> **Even if every atom in the universe were a quantum computer, they couldn't exhaust this space before the heat death of the cosmos.**
### 3. 量子安全性
### 3. Quantum Resistance
| 量子算法 | 目标 | 对 ChaosCrypt 的效果 |
|----------|------|------------------------|
| **Shor** | 分解质数、离散对数 | ❌ **无效** – 没有数论结构 |
| **Grover** | 对称加密加速 | ❌ **无效** – 空间 10⁵⁶³²,开根号后 10²⁸¹⁶,依然远大于 10⁸⁰ |
| Quantum Alg | Target | Effect on ChaosCrypt |
|-------------|--------|----------------------|
| **Shor** | Integer factorization, discrete log | ❌ **Ineffective** – no number‑theoretic structure |
| **Grover** | Symmetric encryption speedup | ❌ **Ineffective** – space 10⁵⁶³², sqrt gives 10²⁸¹⁶, still >> 10⁸⁰ |
**结论:ChaosCrypt 对抗已知量子攻击完全免疫。**
**Conclusion: ChaosCrypt is fully immune to known quantum attacks.**
### 4. 经典攻击方式评估
### 4. Classical Attack Vectors
| 攻击方式 | 是否可行 | 原因 |
|----------|----------|------|
| 频率分析 | ❌ | 随机替换表破坏频率分布 |
| 周期分析 | ❌ | 密钥长度 ≥ 明文,无循环 |
| 已知明文攻击 | ❌ | 非线性操作 → 超定方程组无解 |
| 选择明文攻击 | ❌ | 即使可控输入也无法反推黑盒映射 |
| 差分/线性攻击 | ❌ | 无代数结构,无法建立差分链 |
| 暴力枚举 | ❌ | 空间 10⁵⁶³²,物理上不可能 |
| Attack | Feasible? | Reason |
|--------|-----------|--------|
| Frequency analysis | ❌ | Random substitution destroys frequency patterns |
| Periodicity analysis | ❌ | Key length ≥ plaintext, no cycles |
| Known‑plaintext attack | ❌ | Nonlinear ops → overdetermined system with no solution |
| Chosen‑plaintext attack | ❌ | Even controllable input can't invert the black‑box mapping |
| Differential/linear | ❌ | No algebraic structure to build differential chains |
| Brute force | ❌ | Space 10⁵⁶³², physically impossible |
**唯一现实威胁**:盗取 `.key` 文件 + 窃取用户密码(端侧攻击,与算法无关)。
**The only real threat**: Theft of `.key` file + password (client‑side compromise, unrelated to the algorithm).
---
## 为什么这玩意儿真的安全?(不服来辩版)
## Why This Is Actually Secure (No‑BS Edition)
**总之就是安全——真·安全。** 🤷‍♂️
**Bottom line: It's secure — genuinely secure.** 🤷‍♂️
我寻思着,总不能所有加密算法都得围着椭圆曲线和质数分解转,然后等 NIST 给你盖个戳才算"安全"吧?那算什么东西?**垄断啊?** 🤣
Look, not every encryption algorithm has to revolve around elliptic curves and prime factorization, waiting for NIST to stamp it "secure." That's not security—that's **a monopoly.** 🤣
再说了,美国政府什么心思你猜不透。**Dual_EC_DRBG 的事儿这么快就忘了?** NIST 认证的、标准化的、全世界用了好几年的算法——结果里面养着 NSA 的后门。标准管个屁用。
And let's not forget **Dual_EC_DRBG** — NIST‑certified, standardized, used worldwide for years… and it had an NSA backdoor baked in. So much for standards.
所以别跟我扯什么"学术界验证"、"第三方审计"、"算法标准认证"。我就问一句:
So don't give me "academic verification," "third‑party audit," or "standard certification." I'll ask you one question:
**只有这些"标准"算法才能叫安全?**
**Are only those "standard" algorithms allowed to be secure?**
- **安全 ≠ 数学复杂**
- **安全 ≠ NIST 认证**
- **Secure ≠ mathematically complex**
- **Secure ≠ NIST‑approved**
---
来,咱们看看所谓的"标准算法"都什么下场:
Let's see how those "standard" algorithms fare:
| 算法 | 密钥空间 | 量子下场 |
|------|----------|----------|
| AES-256 | 10⁷⁷ | Grover 减半到 10³⁸ → 理论上可破 |
| RSA-2048 | 10⁶¹⁶ | Shor 一来直接秒死 🔥 |
| ECC | 10⁶¹⁶ | 同上,Shor 直接扼杀 |
| Algorithm | Key Space | Quantum Fate |
|-----------|-----------|--------------|
| AES‑256 | 10⁷⁷ | Grover halves it to 10³⁸ → theoretically breakable |
| RSA‑2048 | 10⁶¹⁶ | Shor kills it instantly 🔥 |
| ECC | 10⁶¹⁶ | Same, Shor shuts it down |
再看看我这个:
Now look at this:
| 算法 | 密钥空间 | 量子下场 |
|------|----------|----------|
| **ChaosCrypt** | **10⁵⁶³²** | **Shor 无从下手,Grover 打了等于没打** ✅ |
| Algorithm | Key Space | Quantum Fate |
|-----------|-----------|--------------|
| **ChaosCrypt** | **10⁵⁶³²** | **Shor has nothing to attack, Grover barely scratches it** ✅ |
**10⁵⁶³² 什么概念?**
**10⁵⁶³² — what does that mean?**
全宇宙原子总数才 10⁸⁰。就算把全宇宙每个原子都变成一台量子计算机,从宇宙大爆炸算到今天,**也算不完这个空间的一个零头。**
The universe has ~10⁸⁰ atoms. Even if every atom were a quantum computer running from the Big Bang to now, they wouldn't finish a fraction of this space.
AES 的 10⁷⁷ 在它面前就像一粒沙子对比整个银河系。
AES's 10⁷⁷ is a grain of sand compared to the Milky Way.
---
**RSA 美丽吧?标准吧?数学优美吧?**
**RSA is beautiful, right? Standard? Mathematically elegant?**
但恰恰因为**太数学了**,所以 Shor 一发入魂,直接物理超度。
But precisely because it's **too mathematical**, Shor one‑shots it.
**数学上越好看,结构越清晰,攻击者就越开心**——因为你有方程,他就能解;你有规律,他就能抓;你有结构,他就能拆。
**The prettier the math, the clearer the structure, the happier the attacker** — because you have equations they can solve, patterns they can exploit, structure they can dismantle.
我的算法呢?
My algorithm?
- 替换表?随机打的,没有规律。
- 翻转模式?硬编码数组,没有方程。
- 密钥派生?黑盒操作,解不出来。
- Substitution? Randomly shuffled — no pattern.
- Flip pattern? Hardcoded array — no equation.
- Key derivation? Black‑box mix — unsolvable.
**攻击者想写个方程都写不出来,想用代数工具都找不到切入点。**
**An attacker can't even write an equation. There's no algebraic handle to grab.**
---
**所以这算法有什么问题?**
**So what's wrong with this algorithm?**
- ❌ 没有"第三方安全审计"
- ❌ 没有"算法标准认证"
- ❌ 没有"学术界验证"
- ❌ 并且"看起来肥肠初级"
- ❌ No "third‑party security audit"
- ❌ No "algorithm standard certification"
- ❌ No "academic validation"
- ❌ And it "looks pretty amateur"
**除此之外,没有任何问题。** 🤷‍♂️
**Other than that, absolutely nothing.** 🤷‍♂️
看起来初级就初级,**你能攻破么?不能!**
Looks amateur? Fine. **Can you break it? No.**
安全这两个字,只关心**实战**,不关心**评价**和**认证**。
Security is about **real‑world results**, not **reviews** or **certifications**.
- Dual_EC_DRBG 有认证有标准有审计——结果呢?后门。
- 我这个啥都没有——结果呢?**你破不了。**
- Dual_EC_DRBG had certs, standards, audits — and a backdoor.
- This has none of that — and **you can't break it.**
**能被黑客破解的就是垃圾,破解不了的就是真神。**
**If hackers can crack it, it's garbage. If they can't, it's the real deal.**
这玩意儿你实说,**你找不出来毛病!** 😏🔥
Seriously — **find a flaw. I dare you.** 😏🔥
---
## 💬 ChaosCryptChat 混沌加密聊天(v2.0 新增)
## 💬 ChaosCryptChat (v2.0 New)
**ChaosCryptChat** 是基于 ChaosCrypt 混沌加密内核构建的端到端加密聊天系统。所有聊天内容(文本、图片、文件、语音)在发送前均经混沌加密,服务器与中间节点无法读取任何消息。
**ChaosCryptChat** is an end‑to‑end encrypted chat system built on the ChaosCrypt kernel. All content (text, images, files, voice) is chaos‑encrypted before sending—servers and middlemen cannot read any messages.
### 核心特性
### Core Features
| 特性 | 说明 |
|------|------|
| 🔗 **端到端加密** | 所有消息客户端本地加密,服务器只做中继,不持有群密钥 |
| ☁️ **双群模式** | 🔗 端到端 P2P 直连 + ☁️ 中央服务器(解决 NAT 穿透) |
| 🎤 **语音消息** | 录音 → 混沌加密 → 发送 → 解密播放 |
| 🖼️ **图片/文件** | 二进制数据混沌加密传输,支持任意文件类型 |
| 👥 **群管理** | 创建群、加入群、群名、公告、踢人、群主审批 |
| 🚫 **消息撤回** | 2 分钟内可撤回自己的消息 |
| 🔑 **每用户密钥** | 每用户独立密钥认证,防止冒充他人 |
| 📜 **历史记录** | SQLite 本地存储聊天历史(重启不丢) |
| 🛡️ **HMAC 校验** | 每条消息带 HMAC 签名,防篡改、防伪造 |
| 📱 **密钥分享** | 群密钥支持复制 / 二维码 / 文件三种方式分享 |
| Feature | Description |
|---------|-------------|
| 🔗 **End‑to‑end encryption** | All messages encrypted client‑side; server only relays, holds no group keys |
| ☁️ **Two group modes** | 🔗 P2P direct + ☁️ Central server (NAT traversal) |
| 🎤 **Voice messages** | Record → chaos encrypt → send → decrypt & play |
| 🖼️ **Images / Files** | Binary data encrypted with ChaosCrypt, supports any file type |
| 👥 **Group management** | Create, join, group name, announcements, kick, owner approval |
| 🚫 **Message recall** | Recall within 2 minutes of sending |
| 🔑 **Per‑user keys** | Each user has an independent authentication key to prevent impersonation |
| 📜 **History** | SQLite local storage (persists across restarts) |
| 🛡️ **HMAC verification** | Every message carries an HMAC signature to prevent tampering and forgery |
| 📱 **Key sharing** | Group key can be shared via copy / QR code / file |
### 两种群模式
### Two Group Modes
**① 端到端(P2P)群聊**:群主即服务器,成员直连群主主机,适合局域网或公网 IP 场景。群密钥由群主生成并分享给成员。
**① End‑to‑End (P2P) Group**: The group owner acts as the server; members connect directly to the owner's host. Ideal for LAN or public‑IP environments. The owner generates the group key and shares it with members.
**② 中央服务器群聊**:运行 `server.py`(公网 IP)解决 NAT 穿透。服务器只负责用户认证、群成员管理、消息中继——**不持有群密钥,无法解密任何消息**。
**② Central Server Group**: Run `server.py` (public IP) to handle NAT traversal. The server only handles user authentication, group membership, and message relaying—**it does not hold group keys and cannot decrypt any messages.**
### 快速启动
### Quick Start
#### 启动聊天客户端
#### Launch the Chat Client
```bash
cd ChaosCryptChat
python qtmain.py
```
#### 启动中央服务器(可选,公网/NAT 场景)
#### Launch the Central Server (optional, for public/NAT scenarios)
```bash
cd ChaosCryptChat
python server.py 8666
```
#### 安装依赖
#### Install Dependencies
```bash
pip install PyQt5 # 必需,GUI 界面
pip install pygame # 语音播放(可选)
pip install sounddevice numpy # 录音(可选,或 pyaudio)
pip install Pillow # 图片显示(可选)
pip install qrcode # 群密钥二维码(可选)
pip install PyQt5 # Required, GUI
pip install pygame # Audio playback (optional)
pip install sounddevice numpy # Recording (optional, or pyaudio)
pip install Pillow # Image display (optional)
pip install qrcode # Group key QR codes (optional)
```
> 除 PyQt5 外均为可选依赖,未安装时对应功能自动禁用。
> Only PyQt5 is required; all others are optional. Missing dependencies disable their respective features gracefully.
### 使用流程
### Usage Workflow
1. **注册/登录**:启动后创建本地账户(PBKDF2 密码哈希,支持自动登录)
2. **创建群**:点击「📡 创建群」,将群密钥复制/生成二维码分享给好友
3. **加入群**:点击「📥 加入群」,粘贴群密钥或扫码加入
4. **开始聊天**:发送文本/图片/文件/语音;右键消息可撤回、分享、下载;群主可踢人、设公告、改群名
1. **Register / Login**: Create a local account on startup (PBKDF2 password hash, auto‑login supported)
2. **Create a Group**: Click 「📡 Create Group」, copy the group key or generate a QR code to share with friends
3. **Join a Group**: Click 「📥 Join Group」, paste the group key or scan the QR code
4. **Start Chatting**: Send text, images, files, voice messages; right‑click to recall, share, or download; group owners can kick, set announcements, and change group names
---
## 快速开始
## Quick Start
### 安装
### Installation
```bash
# 克隆仓库
# Clone the repository
git clone https://gitcode.com/dvsxt/chaoscrypt.git
git clone https://github.com/dvs-dvsxt/ChaosCrypt.git
cd chaoscrypt
# 核心模块零依赖,Python 3.6+ 即可;ChaosCryptChat 需 PyQt5
# Core module has zero dependencies — Python 3.6+ only
# ChaosCryptChat requires PyQt5
```
### 五分钟上手
### Five‑Minute Example
```python
from chaoscrypt import EncryptionSystem
# 初始化(自动加载默认密钥,不存在则生成)
# Initialize (auto‑loads default key; generates one if missing)
crypto = EncryptionSystem()
# 加密
# Encrypt
cipher = crypto.encrypt("Hello World", user_password="MyP@ssw0rd2024!")
print(cipher)
# 解密
# Decrypt
plain = crypto.decrypt(cipher, user_password="MyP@ssw0rd2024!")
print(plain) # Hello World
```
### 命令行交互
### Command‑Line Interactive Mode
```bash
python chaoscrypt.py
@@ -347,51 +349,51 @@ python chaoscrypt.py
---
## 使用指南
## Usage Guide
### 交互菜单
### Interactive Menu
```
请选择操作:
1. 使用默认密钥加密
2. 使用默认密钥解密
3. 生成新密钥(覆盖默认)
4. 使用指定密钥文件加密
5. 使用指定密钥文件解密
6. 生成密钥并保存到当前文件夹
7. 查看当前密钥信息
8. 退出
Please select an action:
1. Encrypt using the default key
2. Decrypt using the default key
3. Generate a new key (overwrite default)
4. Encrypt using a specified key file
5. Decrypt using a specified key file
6. Generate a key and save to current folder
7. View current key info
8. Exit
```
### 密钥文件
### Key File
密钥文件以混淆形式存储,防止普通用户直接阅读。内容包括:
Keys are stored in an obfuscated format to prevent casual reading. Contents include:
- `upper_mapping` – 大写字母随机替换表
- `lower_mapping` – 小写字母随机替换表
- `digit_mapping` – 数字→字符映射
- `equal_mapping` – 等号映射
- `long_key` – 4096位十六进制密钥
- `short_key` – 512位十六进制密钥
- `generated_at` – 生成时间戳
- `upper_mapping` – random substitution for uppercase letters
- `lower_mapping` – random substitution for lowercase letters
- `digit_mapping` – digit‑to‑character mapping
- `equal_mapping` – equal‑sign mapping
- `long_key` – 4096‑bit hexadecimal key
- `short_key` – 512‑bit hexadecimal key
- `generated_at` – timestamp
---
## API 参考
## API Reference
### `EncryptionSystem(key_file=None)`
初始化加密系统。
Initialize the encryption system.
**参数:**
- `key_file` (str, optional) – 密钥文件路径。若为 None,自动加载 `encryption.key`;若不存在则生成。
**Parameters:**
- `key_file` (str, optional) – path to the key file. If `None`, loads `encryption.key`; generates one if missing.
**示例:**
**Example:**
```python
# 使用默认密钥
# Use default key
crypto = EncryptionSystem()
# 使用指定密钥
# Use a custom key file
crypto = EncryptionSystem("my_key.key")
```
@@ -399,16 +401,16 @@ crypto = EncryptionSystem("my_key.key")
### `encrypt(plaintext, user_password)`
加密明文。
Encrypt plaintext.
**参数:**
- `plaintext` (str) – 待加密文本
- `user_password` (str) – 用户密码
**Parameters:**
- `plaintext` (str) – text to encrypt
- `user_password` (str) – user password
**返回:**
- `str` – 十六进制密文
**Returns:**
- `str` – hexadecimal ciphertext
**示例:**
**Example:**
```python
cipher = crypto.encrypt("Hello", "myPass123")
```
@@ -417,16 +419,16 @@ cipher = crypto.encrypt("Hello", "myPass123")
### `decrypt(ciphertext, user_password)`
解密密文。
Decrypt ciphertext.
**参数:**
- `ciphertext` (str) – 十六进制密文
- `user_password` (str) – 用户密码
**Parameters:**
- `ciphertext` (str) – hexadecimal ciphertext
- `user_password` (str) – user password
**返回:**
- `str` – 解密后的明文,失败时返回错误信息
**Returns:**
- `str` – decrypted plaintext, or an error message on failure
**示例:**
**Example:**
```python
plain = crypto.decrypt("a1b2c3...", "myPass123")
```
@@ -435,100 +437,100 @@ plain = crypto.decrypt("a1b2c3...", "myPass123")
### `generate_keys(save_path=None)`
生成新的随机密钥并保存。
Generate new random keys and save them.
**参数:**
- `save_path` (str, optional) – 保存路径,默认 `key_{timestamp}.key`
**Parameters:**
- `save_path` (str, optional) – save path; defaults to `key_{timestamp}.key`
**返回:**
- `str` – 保存的文件路径
**Returns:**
- `str` – the saved file path
---
### `print_keys()`
打印当前密钥信息。
Print the current key information.
---
## 常见问题
## FAQ
**Q:这算法经过审计吗?**
A:没有。但我们认为**没有审计 ≠ 不安全**,Dual_EC_DRBG 经过审计却是后门。审计只是参考,不是真理。
**Q: Has this algorithm been audited?**
A: No. But we believe **no audit ≠ insecure** — Dual_EC_DRBG was audited and backdoored. Audits are references, not truth.
**Q:为什么不直接用 AES?**
A:AES 很好,但它是"标准"算法,有代数结构,Grover 可以加速。我们选择另一条路——**完全随机、无结构、超大空间**。
**Q: Why not just use AES?**
A: AES is great, but it's a "standard" algorithm with algebraic structure, and Grover can speed it up. We chose a different path — **fully random, structure‑free, and enormous.**
**Q:如果黑客拿到了 `.key` 文件和密文,但不知道密码呢?**
A:那他就只能暴力破解密码。如果密码是 12 位以上强密码,破解时间以年为单位。
**Q: What if an attacker gets the `.key` file and the ciphertext, but not the password?**
A: Then they're left with brute‑forcing the password. If the password is 12+ characters strong, that's years of work.
**Q:如果黑客同时拿到了 `.key`、密文、密码呢?**
A:那你的系统已经不属于"加密被攻破",而是"钥匙被偷"——这是端侧安全问题,任何加密算法都防不住。
**Q: What if the attacker gets the `.key`, ciphertext, and password?**
A: Then your system isn't "crypto broken" — it's "keys stolen." That's a client‑side security issue, which no encryption algorithm can prevent.
**Q:这算法有数学证明吗?**
A:有。证明如下:
- 无法建立数学模型 → 无代数攻击路径
- 密钥空间 10⁵⁶³² → 暴力不可能
- 量子加速无效 → 抗量子
**Q: Is there a mathematical proof for this?**
A: Yes. The proof is:
- No mathematical model can be constructed → no algebraic attacks
- Key space 10⁵⁶³² → brute force impossible
- Quantum speedups don't help → quantum‑resistant
这个证明比任何"归约到难问题"都更硬——因为**没有结构可归约,只能枚举**。
This proof is stronger than any "reduction to a hard problem" — because **there's no structure to reduce, only exhaustive search.**
**Q:看起来好初级,真能用?**
A:初级和安全没有半毛钱关系。你长得好看能挡子弹吗?能破就是能破,不能破就是不能破。**你破一个试试?**
**Q: It looks so amateurish — is it actually usable?**
A: Looking amateur and being secure have nothing to do with each other. Can you break it or not? **Try it.**
**Q:ChaosCryptChat 聊天安全吗?**
A:端到端加密——消息在客户端用群密钥混沌加密,服务器只转发密文、不持有密钥。即使服务器被入侵也拿不到聊天内容。
**Q: Is ChaosCryptChat secure?**
A: End‑to‑end — messages are encrypted client‑side with the group key; the server forwards only ciphertext and holds no keys. Even if the server is breached, chat contents remain private.
**Q:聊天密钥怎么分享?**
A:群主创建群后生成群密钥,可通过复制文本、二维码、密钥文件三种方式分享。请走可信渠道传递,避免被中间人截获。
**Q: How do I share the group key?**
A: After creating a group, the owner can share the key via copied text, QR code, or key file. Use a trusted channel to avoid MITM interception.
**Q:ChaosCryptChat 需要公网 IP 吗?**
A:不需要。局域网用 P2P 直连即可;跨网络用中央服务器(server.py)中继,解决 NAT 穿透。
**Q: Does ChaosCryptChat require a public IP?**
A: No. Use P2P for LAN; for cross‑network, the central server (`server.py`) relays traffic to handle NAT.
---
## 项目结构
## Project Structure
```
chaoscrypt/
├── chaoscrypt.py # 主程序(加密/解密/密钥管理)
├── README.md # 本文档
├── SECURITY.md # 安全说明文档
└── ChaosCryptChat/ # 💬 混沌加密聊天(v2.0 新增)
├── qtmain.py # PyQt5 聊天客户端(端到端加密)
└── server.py # ☁️ 中央服务器(NAT 穿透 / 消息中继)
├── chaoscrypt.py # Main program (encrypt/decrypt/key management)
├── README.md # This document
├── SECURITY.md # Security details
└── ChaosCryptChat/ # 💬 Encrypted Chat (v2.0 new)
├── qtmain.py # PyQt5 chat client (E2E encrypted)
└── server.py # ☁️ Central server (NAT traversal / message relay)
```
核心就三个文件,零依赖;ChaosCryptChat 是 v2.0 新增的加密聊天模块。
The core is just three files with zero dependencies; ChaosCryptChat is the v2.0 addition.
---
## 免责声明
## Disclaimer
> **本系统仅供学习研究使用。**
> 作者不承担因密钥文件泄露、密码失窃、端侧入侵等导致的任何数据损失责任。
> 生产环境请确保 `.key` 文件和用户密码均安全存储,并考虑强制用户使用强密码策略。
> **ChaosCryptChat** 服务器不持有群密钥,但会记录用户登录信息与消息中继日志,请谨慎选择信任的服务器。
> 聊天密钥由群主分享,请通过可信渠道传递;即使服务器被攻陷也不会泄露历史聊天内容。
> **This system is for educational and research purposes only.**
> The author assumes no liability for data loss due to key file leakage, password theft, or client‑side compromise.
> In production, ensure the `.key` file and user password are stored securely, and enforce strong password policies.
> **ChaosCryptChat** servers do not hold group keys, but they do log login information and relay metadata—choose your server wisely.
> Group keys are shared by the group owner; transmit them over trusted channels. Even if the server is compromised, historical chat content remains private.
---
## 📜 许可证
## 📜 License
MIT License — 你可以自由使用、修改、分发,但请保留原作者声明。
MIT License — you are free to use, modify, and distribute, but please retain the original attribution.
---
## 🙏 致谢
## 🙏 Acknowledgments
感谢所有认真看完这份文档的人。
你是极少数愿意**用逻辑判断安全,而不是用头衔判断安全**的人。
Thank you to everyone who read this document carefully.
You are among the few who judge security by **logic**, not by **credentials**.
---
**"安全应该由攻击难度定义,而不是由某个机构盖章定义。"**
—— ChaosCrypt 设计哲学
**"Security should be defined by the difficulty of attack, not by a stamp from an institution."**
— ChaosCrypt Design Philosophy
---
**Happy Encrypting! 🔐**
**Happy Encrypting! 🔐**
+343 -231
View File
@@ -1,3 +1,7 @@
"""
A multi-layer encryption system with key management, substitution ciphers,
XOR operations, and dynamic key derivation.
"""
import base64
import json
@@ -5,12 +9,23 @@ import os
import time
from datetime import datetime
class EncryptionSystem:
"""Main encryption engine with key-based transformation layers."""
def __init__(self, key_file=None, key_password=None):
"""
Initialize the encryption system with an optional key file.
Args:
key_file: Path to the encryption key file.
key_password: Password for decrypting the key file.
"""
self.key_file = key_file
self.key_password = key_password
self.keys_loaded = False
# Base64 special character mappings for safe transport
self.special_encrypt = {
'+': '.',
'/': "'",
@@ -20,41 +35,49 @@ class EncryptionSystem:
'.': '+',
"'": '/'
}
self.flip_pattern = None
# Try loading the key file if provided or find default
if key_file:
if os.path.exists(key_file):
if key_password is None:
key_password = input(f"请输入密钥文件 {key_file} 的密码: ")
key_password = input(f"Enter password for key file {key_file}: ")
self._load_keys(key_file, key_password)
self.keys_loaded = True
else:
print(f"⚠️ 密钥文件 {key_file} 不存在")
print(f"⚠️ Key file {key_file} not found")
self.keys_loaded = False
else:
default_key = "encryption.key"
if os.path.exists(default_key):
self.key_file = default_key
if key_password is None:
key_password = input(f"请输入密钥文件 {default_key} 的密码: ")
key_password = input(f"Enter password for key file {default_key}: ")
self._load_keys(default_key, key_password)
self.keys_loaded = True
else:
print("=" * 60)
print("首次启动,请先生成密钥文件")
print("First launch detected. Please generate a key file first.")
print("=" * 60)
self.keys_loaded = False
# ----------------------------------------------------------------------
# Key generation utilities
# ----------------------------------------------------------------------
def _generate_random_alphabet(self, lowercase=False):
"""Generate a shuffled alphabet string."""
chars = list("abcdefghijklmnopqrstuvwxyz" if lowercase else "ABCDEFGHIJKLMNOPQRSTUVWXYZ")
n = len(chars)
# Fisher-Yates shuffle using secure random bytes
for i in range(n - 1, 0, -1):
j = int.from_bytes(os.urandom(1), 'big') % (i + 1)
chars[i], chars[j] = chars[j], chars[i]
return ''.join(chars)
def _generate_random_digit_mapping(self):
"""Create a random mapping for digits 0-9 to alphabet characters."""
digits = list("0123456789")
mapping_chars = list("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")
n = len(mapping_chars)
@@ -67,72 +90,69 @@ class EncryptionSystem:
return mapping
def _generate_random_equal_mapping(self):
"""Generate mapping for Base64 padding count (0-3)."""
chars = list("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")
n = len(chars)
for i in range(n - 1, 0, -1):
j = int.from_bytes(os.urandom(1), 'big') % (i + 1)
chars[i], chars[j] = chars[j], chars[i]
mapping = {
return {
'0': chars[0],
'1': chars[1],
'2': chars[2],
'3': chars[3]
}
return mapping
def _generate_random_flip_pattern(self):
pattern = []
for _ in range(10):
bit = int.from_bytes(os.urandom(1), 'big') % 2
pattern.append(bit)
return pattern
"""Generate a 10-bit pattern for case-flipping."""
return [int.from_bytes(os.urandom(1), 'big') % 2 for _ in range(10)]
def _generate_long_key(self, length=4096):
"""Generate a long hex key (4096 chars by default)."""
chars = "0123456789abcdef"
result = []
for _ in range(length):
idx = int.from_bytes(os.urandom(1), 'big') % 16
result.append(chars[idx])
return ''.join(result)
return ''.join(chars[int.from_bytes(os.urandom(1), 'big') % 16] for _ in range(length))
def _generate_short_key(self, length=512):
"""Generate a short hex key (512 chars by default)."""
chars = "0123456789abcdef"
result = []
for _ in range(length):
idx = int.from_bytes(os.urandom(1), 'big') % 16
result.append(chars[idx])
return ''.join(result)
return ''.join(chars[int.from_bytes(os.urandom(1), 'big') % 16] for _ in range(length))
# ----------------------------------------------------------------------
# Key obfuscation and persistence
# ----------------------------------------------------------------------
def _obfuscate_keys(self, keys_data):
"""Obfuscate key data using base64 + reversal + Caesar shift."""
json_str = json.dumps(keys_data)
b64 = base64.b64encode(json_str.encode()).decode()
reversed_b64 = b64[::-1]
shifted = ''.join([chr((ord(c) + 1) % 128) for c in reversed_b64])
final = base64.b64encode(shifted.encode()).decode()
return final
shifted = ''.join(chr((ord(c) + 1) % 128) for c in reversed_b64)
return base64.b64encode(shifted.encode()).decode()
def _deobfuscate_keys(self, obfuscated_data):
"""Reverse the obfuscation to recover original key data."""
try:
shifted = base64.b64decode(obfuscated_data.encode()).decode()
reversed_b64 = ''.join([chr((ord(c) - 1) % 128) for c in shifted])
reversed_b64 = ''.join(chr((ord(c) - 1) % 128) for c in shifted)
b64 = reversed_b64[::-1]
json_str = base64.b64decode(b64.encode()).decode()
return json.loads(json_str)
except Exception:
raise Exception("密钥文件损坏")
except Exception as exc:
raise Exception("Key file corrupted") from exc
def _xor_encrypt_data(self, data, password):
result = []
"""XOR encrypt data with a password, returning hex string."""
key_len = len(password)
for i, char in enumerate(data):
xor_result = ord(char) ^ ord(password[i % key_len])
result.append(f"{xor_result:02x}")
return ''.join(result)
return ''.join(
f"{ord(char) ^ ord(password[i % key_len]):02x}"
for i, char in enumerate(data)
)
def _xor_decrypt_data(self, hex_data, password):
"""XOR decrypt hex data with a password."""
try:
result = []
key_len = len(password)
result = []
for i in range(0, len(hex_data), 2):
if i + 1 < len(hex_data):
hex_byte = hex_data[i:i+2]
@@ -143,17 +163,28 @@ class EncryptionSystem:
return None
def generate_keys(self, save_path=None, key_password=None):
"""
Generate a fresh set of encryption keys and save to a key file.
Args:
save_path: Path to save the key file (default: encryption.key).
key_password: Password to protect the key file.
Returns:
The password used, or None if generation failed.
"""
if key_password is None:
key_password = input("请设置密钥文件密码: ")
confirm = input("请再次输入密码确认: ")
key_password = input("Set key file password: ")
confirm = input("Confirm password: ")
if key_password != confirm:
print("❌ 密码不匹配")
print("❌ Passwords do not match")
return None
print("=" * 60)
print("正在生成随机密钥...")
print("Generating random keys...")
print("=" * 60)
# Generate all key components
self.upper_mapping = self._generate_random_alphabet(lowercase=False)
self.lower_mapping = self._generate_random_alphabet(lowercase=True)
self.digit_mapping = self._generate_random_digit_mapping()
@@ -161,10 +192,12 @@ class EncryptionSystem:
self.flip_pattern = self._generate_random_flip_pattern()
self.long_key = self._generate_long_key(4096)
self.short_key = self._generate_short_key(512)
# Build reverse mappings
self.digit_reverse = {v: k for k, v in self.digit_mapping.items()}
self.equal_reverse = {v: k for k, v in self.equal_mapping.items()}
# Bundle keys into a dictionary
keys_data = {
'upper_mapping': self.upper_mapping,
'lower_mapping': self.lower_mapping,
@@ -175,30 +208,36 @@ class EncryptionSystem:
'short_key': self.short_key,
'generated_at': datetime.now().isoformat()
}
# Obfuscate and encrypt the key data
obfuscated = self._obfuscate_keys(keys_data)
encrypted = self._xor_encrypt_data(obfuscated, key_password)
if save_path is None:
save_path = "encryption.key"
with open(save_path, 'w') as f:
f.write(encrypted)
self.key_file = save_path
self.key_password = key_password
self.keys_loaded = True
self._build_maps()
print(f"✅ 密钥已生成并保存到: {save_path}")
print(f"✅ Keys generated and saved to: {save_path}")
print("=" * 60)
return save_path
# ----------------------------------------------------------------------
# Internal helpers
# ----------------------------------------------------------------------
def _build_maps(self):
"""Build encryption and decryption maps from shuffled alphabets."""
self.upper_original = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
self.lower_original = "abcdefghijklmnopqrstuvwxyz"
self.encrypt_map = {}
self.decrypt_map = {}
for i in range(26):
@@ -208,18 +247,19 @@ class EncryptionSystem:
self.decrypt_map[self.lower_mapping[i]] = self.lower_original[i]
def _load_keys(self, key_file, key_password):
"""Load and decrypt keys from a key file."""
try:
with open(key_file, 'r') as f:
encrypted_data = f.read()
decrypted = self._xor_decrypt_data(encrypted_data, key_password)
if decrypted is None:
print("❌ 密码错误")
print("❌ Incorrect password")
self.keys_loaded = False
return
keys_data = self._deobfuscate_keys(decrypted)
self.upper_mapping = keys_data['upper_mapping']
self.lower_mapping = keys_data['lower_mapping']
self.digit_mapping = keys_data['digit_mapping']
@@ -227,25 +267,26 @@ class EncryptionSystem:
self.flip_pattern = keys_data['flip_pattern']
self.long_key = keys_data['long_key']
self.short_key = keys_data['short_key']
self.digit_reverse = {v: k for k, v in self.digit_mapping.items()}
self.equal_reverse = {v: k for k, v in self.equal_mapping.items()}
self.key_password = key_password
self._build_maps()
self.keys_loaded = True
print(f"✅ 密钥已从 {key_file} 加载")
print(f"✅ Keys loaded from {key_file}")
except Exception:
print("❌ 加载失败")
print("❌ Loading failed")
self.keys_loaded = False
def _ensure_printable(self, text):
"""Force all characters into printable ASCII range (32-126)."""
result = []
for c in text:
val = ord(c)
if val == 124:
if val == 124: # '|' is used as a separator, keep it
result.append('|')
elif val < 32 or val > 126:
val = val % 95 + 32
@@ -254,10 +295,25 @@ class EncryptionSystem:
result.append(c)
return ''.join(result)
# ----------------------------------------------------------------------
# Key derivation
# ----------------------------------------------------------------------
def _mix_keys(self, user_password, target_length):
"""
Mix the user password with the short key using bit operations and swaps.
Args:
user_password: User-provided password.
target_length: Desired output length.
Returns:
A mixed printable string.
"""
if not self.keys_loaded:
raise Exception("密钥未加载")
raise Exception("Keys not loaded")
# Interleave user password and short key
mixed = []
max_len = max(len(user_password), len(self.short_key))
for i in range(max_len):
@@ -265,7 +321,8 @@ class EncryptionSystem:
mixed.append(ord(user_password[i]))
if i < len(self.short_key):
mixed.append(ord(self.short_key[i]))
# Apply bit transformations
for i in range(len(mixed)):
if i % 3 == 0:
mixed[i] = (mixed[i] << 1) & 0xFF
@@ -273,21 +330,24 @@ class EncryptionSystem:
mixed[i] = (mixed[i] >> 1) & 0xFF
else:
mixed[i] = mixed[i] ^ 0x5A
# Swap pairs
for i in range(0, len(mixed) - 3, 4):
mixed[i], mixed[i+3] = mixed[i+3], mixed[i]
mixed[i+1], mixed[i+2] = mixed[i+2], mixed[i+1]
mixed.reverse()
# Convert to printable characters
result = []
for x in mixed:
if x < 32 or x > 126:
x = x % 95 + 32
result.append(chr(x))
result_str = ''.join(result)
# Extend if needed by repeating with variations
if len(result_str) < target_length:
base_key = result_str
final_key = base_key
@@ -297,22 +357,29 @@ class EncryptionSystem:
next_chunk = base_key[::-1]
elif iteration % 3 == 1:
next_chunk = base_key[::-1]
next_chunk = ''.join([chr((ord(c) + iteration) % 95 + 32) for c in next_chunk])
next_chunk = ''.join(chr((ord(c) + iteration) % 95 + 32) for c in next_chunk)
else:
next_chunk = base_key[::-1]
next_chunk = ''.join([chr((ord(c) ^ iteration) % 95 + 32) for c in next_chunk])
next_chunk = ''.join(chr((ord(c) ^ iteration) % 95 + 32) for c in next_chunk)
final_key += next_chunk
iteration += 1
result_str = final_key[:target_length]
return self._ensure_printable(result_str)
def _derive_final_key(self, user_password, text_length):
"""
Derive a final encryption key from the user password and short key.
The process includes mixing, hex conversion, reversal, and extension.
"""
mixed_key = self._mix_keys(user_password, text_length * 2)
hex_key = ''.join([f"{ord(c):02x}" for c in mixed_key])
# Convert to hex and reverse
hex_key = ''.join(f"{ord(c):02x}" for c in mixed_key)
reversed_hex = hex_key[::-1]
# Convert back to printable characters
final_key = []
for i in range(0, len(reversed_hex), 2):
if i + 1 < len(reversed_hex):
@@ -324,9 +391,10 @@ class EncryptionSystem:
final_key.append(chr(val))
except ValueError:
final_key.append('x')
final_key_str = ''.join(final_key)
# Extend if needed
if len(final_key_str) < text_length:
base_key = final_key_str
iteration = 0
@@ -335,22 +403,25 @@ class EncryptionSystem:
next_chunk = base_key[::-1]
elif iteration % 3 == 1:
next_chunk = base_key[::-1]
next_chunk = ''.join([chr((ord(c) + iteration) % 95 + 32) for c in next_chunk])
next_chunk = ''.join(chr((ord(c) + iteration) % 95 + 32) for c in next_chunk)
else:
next_chunk = base_key[::-1]
next_chunk = ''.join([chr((ord(c) ^ iteration) % 95 + 32) for c in next_chunk])
next_chunk = ''.join(chr((ord(c) ^ iteration) % 95 + 32) for c in next_chunk)
final_key_str += next_chunk
iteration += 1
final_key_str = final_key_str[:text_length]
final_key_str = self._ensure_printable(final_key_str)
return final_key_str
return self._ensure_printable(final_key_str)
# ----------------------------------------------------------------------
# Core encryption operations
# ----------------------------------------------------------------------
def _apply_flip(self, text):
"""Apply case-flipping based on the flip pattern."""
if self.flip_pattern is None:
return text
result = []
for i, ch in enumerate(text):
idx = i % len(self.flip_pattern)
@@ -361,15 +432,16 @@ class EncryptionSystem:
return ''.join(result)
def _xor_encrypt_with_final_key(self, text, user_password):
"""XOR encrypt with the derived final key, returning hex."""
final_key = self._derive_final_key(user_password, len(text))
key_len = len(final_key)
result = []
for i, char in enumerate(text):
xor_result = ord(char) ^ ord(final_key[i % key_len])
result.append(f"{xor_result:02x}")
return ''.join(result)
return ''.join(
f"{ord(char) ^ ord(final_key[i % key_len]):02x}"
for i, char in enumerate(text)
)
def _xor_decrypt_with_final_key(self, hex_text, user_password):
"""XOR decrypt with the derived final key."""
try:
text_length = len(hex_text) // 2
final_key = self._derive_final_key(user_password, text_length)
@@ -390,47 +462,35 @@ class EncryptionSystem:
return None
def _substitute_letters(self, text, mapping):
result = []
for char in text:
if char in mapping:
result.append(mapping[char])
else:
result.append(char)
return ''.join(result)
"""Apply a substitution map to letters."""
return ''.join(mapping.get(char, char) for char in text)
def _encode_digit(self, num_str):
result = []
for char in num_str:
if char in self.digit_mapping:
result.append(self.digit_mapping[char])
else:
result.append(char)
return ''.join(result)
"""Encode a digit string using the digit mapping."""
return ''.join(self.digit_mapping.get(char, char) for char in num_str)
def _decode_digit(self, encoded_str):
result = []
for char in encoded_str:
if char in self.digit_reverse:
result.append(self.digit_reverse[char])
else:
result.append(char)
return ''.join(result)
"""Decode a digit string using the reverse digit mapping."""
return ''.join(self.digit_reverse.get(char, char) for char in encoded_str)
def _get_dynamic_key(self, text_length):
"""Generate a dynamic key from the long key, repeated as needed."""
key = self.long_key
while len(key) < text_length:
key += self.long_key
if len(key) < text_length:
repeats = (text_length // len(key)) + 1
key = (key * repeats)[:text_length]
return key[:text_length]
def _xor_encrypt_with_key(self, text, key):
"""XOR encrypt with a fixed key, returning hex."""
key_len = len(key)
result = []
for i, char in enumerate(text):
xor_result = ord(char) ^ ord(key[i % key_len])
result.append(f"{xor_result:02x}")
return ''.join(result)
return ''.join(
f"{ord(char) ^ ord(key[i % key_len]):02x}"
for i, char in enumerate(text)
)
def _xor_decrypt_with_key(self, hex_text, key):
"""XOR decrypt with a fixed key."""
try:
key_len = len(key)
result = []
@@ -448,45 +508,74 @@ class EncryptionSystem:
except Exception:
return None
# ----------------------------------------------------------------------
# Public API
# ----------------------------------------------------------------------
def encrypt(self, plaintext, user_password):
"""
Encrypt plaintext with the given password.
Workflow:
1. Base64 encode the plaintext.
2. Apply letter substitution and case-flipping.
3. Reverse the string and append padding count.
4. XOR encrypt with dynamic key (long key).
5. XOR encrypt with derived final key (user password + short key).
Returns:
Encrypted ciphertext as a hex string.
"""
if not self.keys_loaded:
return "❌ 错误:密钥未加载"
return "❌ Error: Keys not loaded"
# Step 1: Base64 encode and handle special chars
b64 = base64.b64encode(plaintext.encode('utf-8')).decode('utf-8')
equal_count = b64.count('=')
processed = b64
for old, new in self.special_encrypt.items():
processed = processed.replace(old, new)
processed = processed.rstrip('=')
# Step 2: Letter substitution + flip + reverse
sub = self._substitute_letters(processed, self.encrypt_map)
flipped = self._apply_flip(sub)
reversed_text = flipped[::-1]
# Step 3: Append padding count
equal_char = self.equal_mapping[str(equal_count)]
with_equal = f"{reversed_text}|{equal_char}"
# Step 4: Dynamic key (long key) encryption
key_length_str = str(len(with_equal))
key_length_encoded = self._encode_digit(key_length_str)
dynamic_key = self._get_dynamic_key(len(with_equal))
encrypted_by_dynamic = self._xor_encrypt_with_key(with_equal, dynamic_key)
# Step 5: Final encryption with derived key
combined = f"{encrypted_by_dynamic}|{key_length_encoded}"
final_encrypted = self._xor_encrypt_with_final_key(combined, user_password)
return final_encrypted
def decrypt(self, ciphertext, user_password):
"""
Decrypt ciphertext with the given password.
Returns:
The original plaintext, or an error message on failure.
"""
if not self.keys_loaded:
return "❌ 解密失败"
return "❌ Decryption failed"
try:
# Step 1: Decrypt with derived final key
combined = self._xor_decrypt_with_final_key(ciphertext, user_password)
if combined is None:
return "❌ 解密失败"
return "❌ Decryption failed"
# Step 2: Extract hex data and length indicator
if '|' in combined:
parts = combined.split('|')
if len(parts) >= 2:
@@ -498,211 +587,234 @@ class EncryptionSystem:
else:
hex_data = combined
key_length_encoded = 'g'
# Step 3: Decode length and get dynamic key
key_length_str = self._decode_digit(key_length_encoded)
try:
key_length = int(key_length_str)
except ValueError:
key_length = 16
dynamic_key = self._get_dynamic_key(key_length)
# Step 4: Decrypt with dynamic key
xor_decrypted = self._xor_decrypt_with_key(hex_data, dynamic_key)
if xor_decrypted is None:
return "❌ 解密失败"
return "❌ Decryption failed"
# Step 5: Extract main data and padding count
if '|' in xor_decrypted:
main_part, equal_char = xor_decrypted.split('|')
equal_count = int(self.equal_reverse.get(equal_char, '0'))
else:
main_part = xor_decrypted
equal_count = 0
# Step 6: Reverse, flip, substitute
reversed_text = main_part[::-1]
flipped = self._apply_flip(reversed_text)
sub = self._substitute_letters(flipped, self.decrypt_map)
# Step 7: Restore Base64 special chars and padding
for old, new in self.special_decrypt.items():
sub = sub.replace(old, new)
b64_with_equal = sub + '=' * equal_count
if len(b64_with_equal) % 4 != 0:
return "❌ 解密失败"
return "❌ Decryption failed"
# Step 8: Base64 decode
decoded = base64.b64decode(b64_with_equal.encode('utf-8')).decode('utf-8')
return decoded
except Exception:
return "❌ 解密失败"
return "❌ Decryption failed"
def print_keys(self):
"""Display information about the currently loaded keys."""
if not self.keys_loaded:
print("❌ 未加载密钥")
print("❌ Keys not loaded")
return
print("=" * 60)
print("密钥信息")
print("Key Information")
print("=" * 60)
print(f"密钥文件: {self.key_file}")
print(f"大写映射表: {self.upper_mapping}")
print(f"小写映射表: {self.lower_mapping}")
print(f"翻转模式: {self.flip_pattern}")
print(f"长密钥长度: {len(self.long_key)} 位")
print(f"短密钥长度: {len(self.short_key)} 位")
print(f"Key file: {self.key_file}")
print(f"Uppercase mapping: {self.upper_mapping}")
print(f"Lowercase mapping: {self.lower_mapping}")
print(f"Flip pattern: {self.flip_pattern}")
print(f"Long key length: {len(self.long_key)} bits")
print(f"Short key length: {len(self.short_key)} bits")
print("=" * 60)
# ----------------------------------------------------------------------
# CLI Entry Point
# ----------------------------------------------------------------------
def main():
"""Command-line interface for the encryption system."""
print("=" * 60)
print("欢迎使用加密系统")
print("Welcome to the Encryption System")
print("=" * 60)
crypto = None
key_password = None
# Try loading default key file
if os.path.exists("encryption.key"):
key_password = input("请输入默认密钥文件 (encryption.key) 的密码: ")
key_password = input("Enter password for default key file (encryption.key): ")
crypto = EncryptionSystem("encryption.key", key_password)
if not crypto.keys_loaded:
print("❌ 加载失败")
print("❌ Loading failed")
crypto = None
else:
print("\n未找到默认密钥文件,请先生成")
choice = input("是否生成默认密钥文件?(y/n): ").strip().lower()
print("\nDefault key file not found. Please generate one first.")
choice = input("Generate default key file? (y/n): ").strip().lower()
if choice == 'y':
crypto = EncryptionSystem()
key_password = crypto.generate_keys("encryption.key")
if key_password is None:
print("❌ 生成失败")
result = crypto.generate_keys("encryption.key")
if result is None:
print("❌ Generation failed")
crypto = None
else:
print("⚠️ 请使用模式4或5指定密钥文件,或模式6生成新密钥")
print("⚠️ Use options 4, 5, or 6 to manage key files manually.")
# Main interaction loop
while True:
print("\n请选择操作:")
print("1. 使用默认密钥加密")
print("2. 使用默认密钥解密")
print("3. 生成新密钥(覆盖默认)")
print("4. 使用指定密钥文件加密")
print("5. 使用指定密钥文件解密")
print("6. 生成密钥并保存到当前文件夹")
print("7. 查看当前密钥信息")
print("8. 退出")
choice = input("\n请选择操作 (1-8): ").strip()
print("\nSelect an option:")
print("1. Encrypt with default key")
print("2. Decrypt with default key")
print("3. Generate new key (overwrite default)")
print("4. Encrypt with custom key file")
print("5. Decrypt with custom key file")
print("6. Generate key and save to current folder")
print("7. View current key info")
print("8. Exit")
choice = input("\nEnter choice (1-8): ").strip()
if choice == '1':
# Encrypt with default key
if crypto is None or not crypto.keys_loaded:
if os.path.exists("encryption.key"):
if key_password is None:
key_password = input("请输入默认密钥文件密码: ")
key_password = input("Enter default key file password: ")
crypto = EncryptionSystem("encryption.key", key_password)
if not crypto.keys_loaded:
print("❌ 加载失败")
print("❌ Loading failed")
continue
else:
print("❌ 密钥文件不存在")
print("❌ Key file not found")
continue
password = input("请输入加密密码: ")
text = input("请输入要加密的文本: ")
password = input("Enter encryption password: ")
text = input("Enter text to encrypt: ")
if text and password:
encrypted = crypto.encrypt(text, password)
print(f"\n✅ 加密结果: {encrypted}")
print(f"\n✅ Encrypted result: {encrypted}")
elif choice == '2':
# Decrypt with default key
if crypto is None or not crypto.keys_loaded:
if os.path.exists("encryption.key"):
if key_password is None:
key_password = input("请输入默认密钥文件密码: ")
key_password = input("Enter default key file password: ")
crypto = EncryptionSystem("encryption.key", key_password)
if not crypto.keys_loaded:
print("❌ 加载失败")
print("❌ Loading failed")
continue
else:
print("❌ 密钥文件不存在")
print("❌ Key file not found")
continue
password = input("请输入加密密码: ")
text = input("请输入要解密的密文: ")
password = input("Enter encryption password: ")
text = input("Enter ciphertext to decrypt: ")
if text and password:
decrypted = crypto.decrypt(text, password)
print(f"\n✅ 解密结果: {decrypted}")
print(f"\n✅ Decrypted result: {decrypted}")
elif choice == '3':
# Generate and overwrite default key
crypto = EncryptionSystem()
key_password = crypto.generate_keys("encryption.key")
if key_password is None:
print("❌ 生成失败")
result = crypto.generate_keys("encryption.key")
if result is None:
print("❌ Generation failed")
else:
print("✅ 默认密钥已更新")
print("✅ Default key updated")
elif choice == '4':
key_file = input("请输入密钥文件路径: ")
# Encrypt with custom key file
key_file = input("Enter key file path: ")
if not os.path.exists(key_file):
print(f"❌ 文件不存在")
print(f"❌ File not found: {key_file}")
continue
kp = input(f"请输入密钥文件密码: ")
kp = input("Enter key file password: ")
crypto = EncryptionSystem(key_file, kp)
if not crypto.keys_loaded:
print("❌ 加载失败")
print("❌ Loading failed")
continue
password = input("请输入加密密码: ")
text = input("请输入要加密的文本: ")
password = input("Enter encryption password: ")
text = input("Enter text to encrypt: ")
if text and password:
encrypted = crypto.encrypt(text, password)
print(f"\n✅ 加密结果: {encrypted}")
print(f"\n✅ Encrypted result: {encrypted}")
elif choice == '5':
key_file = input("请输入密钥文件路径: ")
# Decrypt with custom key file
key_file = input("Enter key file path: ")
if not os.path.exists(key_file):
print(f"❌ 文件不存在")
print(f"❌ File not found: {key_file}")
continue
kp = input(f"请输入密钥文件密码: ")
kp = input("Enter key file password: ")
crypto = EncryptionSystem(key_file, kp)
if not crypto.keys_loaded:
print("❌ 加载失败")
print("❌ Loading failed")
continue
password = input("请输入加密密码: ")
text = input("请输入要解密的密文: ")
password = input("Enter encryption password: ")
text = input("Enter ciphertext to decrypt: ")
if text and password:
decrypted = crypto.decrypt(text, password)
print(f"\n✅ 解密结果: {decrypted}")
print(f"\n✅ Decrypted result: {decrypted}")
elif choice == '6':
# Generate new key with timestamp
timestamp = int(time.time())
filename = f"key_{timestamp}.key"
crypto = EncryptionSystem()
kp = crypto.generate_keys(filename)
if kp is None:
print("❌ 生成失败")
result = crypto.generate_keys(filename)
if result is None:
print("❌ Generation failed")
else:
print(f"✅ 密钥已保存到: {filename}")
print(f"✅ Key saved to: {filename}")
elif choice == '7':
# Show key info
if crypto is None or not crypto.keys_loaded:
if os.path.exists("encryption.key"):
if key_password is None:
key_password = input("请输入默认密钥文件密码: ")
key_password = input("Enter default key file password: ")
crypto = EncryptionSystem("encryption.key", key_password)
if not crypto.keys_loaded:
print("❌ 加载失败")
print("❌ Loading failed")
continue
else:
print("❌ 未加载密钥")
print("❌ Keys not loaded")
continue
crypto.print_keys()
elif choice == '8':
print("感谢使用,再见!")
print("Goodbye!")
break
else:
print("❌ 无效选择")
print("❌ Invalid choice")
if __name__ == "__main__":
main()
main()