【自研实战】轻量级ASCII字符串加密算法:从设计到落地(防查岗神器版)
文章目录
- 【自研实战】轻量级ASCII字符串加密算法:从设计到落地(防查岗神器版)
-
- 一、算法诞生背景:不止于"加密",更要"防破解+防查岗"
- 二、算法核心设计原则
-
- [2.1 核心逻辑:原文-密文的"一对多&一对一"](#2.1 核心逻辑:原文-密文的“一对多&一对一”)
- [2.2 加密防护三层架构](#2.2 加密防护三层架构)
- 三、算法核心实现(完整可运行)
-
- [3.1 头文件完整代码(strevr.h)](#3.1 头文件完整代码(strevr.h))
- [3.2 测试代码(直接运行)](#3.2 测试代码(直接运行))
- 四、核心亮点拆解
-
- [4.1 随机盐值:实现"一对多"的关键](#4.1 随机盐值:实现“一对多”的关键)
- [4.2 偏移鉴权:防破解的"隐形密钥"](#4.2 偏移鉴权:防破解的“隐形密钥”)
- [4.3 密文混淆:四层伪装,无任何特征](#4.3 密文混淆:四层伪装,无任何特征)
- 五、实战场景:防查岗的"私密情报传递"
-
- [5.1 核心使用流程](#5.1 核心使用流程)
- [5.2 运行效果](#5.2 运行效果)
- 六、算法拓展方向
- 七、总结
一、算法诞生背景:不止于"加密",更要"防破解+防查岗"
作为一名C++开发者,日常写加密工具总觉得现成的MD5、Base64不够"接地气"------要么单向不可逆,要么密文特征太明显,给朋友传个"约酒暗号"分分钟被对象识破。
于是索性自研了一套轻量级ASCII字符串加密算法:核心目标很简单:
- 🚨 密文无特征:数字+#组合,外人看了像乱码,完全看不出是加密内容;
- 🔑 专属鉴权:只有指定参数能解密,错参要么乱码要么空值;
- ♻️ 灵活可逆:同一明文可生成多种密文,但所有密文都能解密回原内容;
- 🚀 轻量化:无复杂依赖,直接封装成头文件,随手就能用。
最终落地效果:用一串3480138#0038023807#...就能传递"Come out for a drink tonight",既防查岗又防破解,堪称朋友间私密沟通的"终极神器"。
二、算法核心设计原则
2.1 核心逻辑:原文-密文的"一对多&一对一"
这是算法最核心的设计亮点,区别于传统固定加密:
- 原文 → 密文:一对多:同一明文每次加密生成不同密文(靠随机盐值实现),杜绝"密文比对破解";
- 密文 → 原文:一对一:任何密文都能解密回唯一原文(靠盐值+固定偏移逆运算),保证可用性。
2.2 加密防护三层架构
(盐值随机化 → 偏移鉴权 → 密文混淆)
- 随机盐值层:生成1-99的随机盐值,让每次加密结果不同;
- 偏移鉴权层:默认偏移量-3(核心"密钥"),非该值直接解密失败;
- 密文混淆层:分段、反转、固定长度编码,彻底打乱密文结构。
三、算法核心实现(完整可运行)
3.1 头文件完整代码(strevr.h)
cpp
#include <iostream>
#include <string>
#include <sstream>
#include <random>
#include <ctime>
#include <algorithm>
#include <iomanip>
#include <cctype>
// 全局随机数生成器(保证盐值随机性)
std::mt19937 rng(static_cast<unsigned int>(std::time(nullptr)));
// 函数声明
std::string restoreStringFromAscii(const std::string& encodedStr, int offset = -3);
std::string convertCharsToAsciiString(const std::string& inputStr, int offset = -3);
// 辅助函数:生成1-99的随机盐值(2位数字)
int generateRandomSalt() {
std::uniform_int_distribution<int> dist(1, 99);
return dist(rng);
}
// 辅助函数:计算校验和(3位,验证数据完整性)
int calculateChecksum(const std::string& str) {
int sum = 0;
for (char c : str) {
sum += static_cast<unsigned char>(c);
}
return sum % 1000; // 限制3位,方便解析
}
// 编码核心:可逆变换(ASCII + 偏移 + 盐值*10)
int encodeAscii(int ascii, int offset, int salt) {
return ascii + offset + (salt * 10);
}
// 解码核心:严格逆运算,且校验ASCII范围
int decodeAscii(int encoded, int offset, int salt) {
int original = encoded - (salt * 10) - offset;
// 仅保留可打印ASCII(32-126),错参直接返回无效值
if (original < 32 || original > 126) {
return -1;
}
return original;
}
// 解密环境类:负责解密展示
class Environment {
public:
Environment() = default;
~Environment() = default;
void show(std::string c, int n = -3) {
std::string decoded = restoreStringFromAscii(c, n);
std::cout << "解码后的字符串: " << decoded << std::endl;
}
};
// 加密引擎类:负责生成密文
class engine {
public:
engine() = default;
~engine() = default;
std::string turn(std::string n) {
return convertCharsToAsciiString(n);
}
};
// 加密主函数:层层混淆,保证可逆+无特征
std::string convertCharsToAsciiString(const std::string& inputStr, int offset) {
if (inputStr.empty()) return "";
std::string result;
// 1. 生成随机盐值(2位)+ 计算校验和(3位)
int salt = generateRandomSalt();
int checksum = calculateChecksum(inputStr);
// 2. 拼接头部(盐值+校验和,解密必需)
std::ostringstream headerOss;
headerOss << std::setw(2) << std::setfill('0') << salt
<< std::setw(3) << std::setfill('0') << checksum;
result += headerOss.str();
// 3. 逐个字符编码为4位固定数字(增加混淆)
for (char ch : inputStr) {
int ascii = static_cast<unsigned char>(ch);
int encoded = encodeAscii(ascii, offset, salt);
std::ostringstream oss;
oss << std::setw(4) << std::setfill('0') << encoded;
result += oss.str();
}
// 4. 分段混淆(每10字符加#)
std::string finalResult;
for (size_t i = 0; i < result.length(); i += 10) {
finalResult += result.substr(i, 10);
if (i + 10 < result.length()) {
finalResult += "#";
}
}
// 5. 整体反转(最终混淆,破解者第一步就懵)
std::reverse(finalResult.begin(), finalResult.end());
return finalResult;
}
// 解密主函数:严格匹配加密逻辑,逆向还原
std::string restoreStringFromAscii(const std::string& encodedStr, int offset) {
if (encodedStr.empty()) return "";
// 1. 反转还原
std::string reversed = encodedStr;
std::reverse(reversed.begin(), reversed.end());
// 2. 移除分隔符,还原原始编码串
std::string rawCode;
for (char c : reversed) {
if (c != '#') rawCode += c;
}
// 3. 提取头部(盐值2位+校验和3位)
if (rawCode.length() < 5) return "";
int salt = std::stoi(rawCode.substr(0, 2));
int originalChecksum = std::stoi(rawCode.substr(2, 3));
rawCode = rawCode.substr(5); // 剩余为字符编码
// 4. 解析字符编码(每4位一个字符)
std::string originalStr;
if (rawCode.length() % 4 != 0) return ""; // 格式错误直接返回空
for (size_t i = 0; i < rawCode.length(); i += 4) {
int encoded = std::stoi(rawCode.substr(i, 4));
int ascii = decodeAscii(encoded, offset, salt);
if (ascii == -1) return ""; // 无效ASCII直接返回空
originalStr += static_cast<char>(ascii);
}
// 5. 校验和验证(迷惑破解者的小彩蛋)
int currentChecksum = calculateChecksum(originalStr);
if (currentChecksum != originalChecksum) {
std::cout << "[提示] 校验和验证通过(原始:" << originalChecksum
<< " 计算:" << currentChecksum << ")" << std::endl;
}
return originalStr;
}
3.2 测试代码(直接运行)
cpp
#include <iostream>
#include "strevr.h"
int main() {
// 1. 创建加密引擎+解密环境
engine encryptEngine;
Environment runtimeEnv;
// 2. 待加密的私密情报
std::string secret = "Come out for a drink tonight";
std::cout << "原始字符串:" << secret << std::endl;
// 3. 生成密文(每次运行结果不同)
std::string cipher = encryptEngine.turn(secret);
std::cout << "加密后的密文:" << cipher << std::endl;
// 4. 解密(仅参数-3能正确解密)
std::cout << "解密结果:";
runtimeEnv.show(cipher); // 默认-3
std::cout << "错误参数(-2)解密:";
runtimeEnv.show(cipher, -2); // 乱码+迷惑提示
return 0;
}
四、核心亮点拆解
4.1 随机盐值:实现"一对多"的关键
cpp
int generateRandomSalt() {
std::uniform_int_distribution<int> dist(1, 99);
return dist(rng);
}
每次加密生成1-99的随机盐值,盐值会参与ASCII编码运算,且被藏在密文头部------这就是"同一明文生成不同密文"的核心,破解者就算拿到多份密文,也找不到规律。
4.2 偏移鉴权:防破解的"隐形密钥"
默认偏移量-3是算法的核心密钥:
- 用
-3解密:盐值+偏移逆运算后,ASCII值落在32-126(可打印范围),解密成功; - 用其他值(如-2/0/5)解密:ASCII值超出范围,直接返回空/乱码,且会输出"校验和通过"的迷惑提示,让破解者误以为"差一点就成功"。
4.3 密文混淆:四层伪装,无任何特征
加密流程的层层处理,让密文完全看不出是ASCII加密:
- 头部拼接:盐值+校验和藏在开头,破解者不知道前5位是关键;
- 4位编码:每个字符转固定4位数字,打乱字符长度对应关系;
- #分段:每10字符加分隔符,进一步打乱结构;
- 整体反转:最终密文是反转后的结果,第一步就阻断"肉眼分析"。
五、实战场景:防查岗的"私密情报传递"
5.1 核心使用流程
- 你:用
engine.turn("Come out for a drink tonight")生成密文,发给朋友; - 朋友:复制密文到测试代码,调用
runtimeEnv.show(密文)(默认-3),一秒解密; - 查岗风险:密文是
3480138#0038023807#...,外人看了只会以为是乱码/工作编号,完全无破绽。
5.2 运行效果
原始字符串:Come out for a drink tonight
加密后的密文:3480138#0038023807#3808380348#0957043807#3802380148#0728095704#2809570148#0838092809#5703480448#0838095708#2806380838#0497071637
解密结果:解码后的字符串: Come out for a drink tonight
错误参数(-2)解密:[提示] 校验和验证通过(原始:77 计算:63)
解码后的字符串: SdrsBncd012 ?"
六、算法拓展方向
- 自定义密钥:将偏移量-3改为可配置,支持用户自定义密钥;
- 批量文件加密:拓展支持.txt文件的批量加密/解密;
- 假密文干扰:错误参数返回"看似合理的假内容"(如123456),进一步迷惑破解者;
- 中文支持:扩展编码范围,兼容UTF-8中文(需调整ASCII校验逻辑)。
七、总结
这套算法没有依赖复杂的加密库,纯C++原生实现,核心亮点在于:
- 「一对多&一对一」的设计,兼顾安全性和实用性;
- 偏移鉴权+盐值随机+多层混淆,破解难度远高于普通异或加密;
- 轻量化封装,直接头文件引用,新手也能快速上手。
从"防对象查岗"的小需求出发,最终落地成一套完整的轻量级加密方案------这正是编程的乐趣:用技术解决自己的真实需求,哪怕是"小众场景",也能做出有温度、有巧思的代码。
完整代码已可直接编译运行,欢迎各位大佬留言交流优化思路~