Skip to content

Commit 9d19d49

Browse files
authored
Code Efficiency Upgrade
Code Efficiency Upgrade
2 parents 172cb2b + 2de5e11 commit 9d19d49

File tree

3 files changed

+100
-326
lines changed

3 files changed

+100
-326
lines changed

README.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ Abracadabra 是表演魔术 (施魔法) 时所念的咒语。
2020
- 随机,加密结果具有随机性。
2121
- 无序,加密的文本如咒语般不可阅读。
2222
- 安心,密码表中已剔除敏感汉字。
23-
- 快速,C++ 快如闪电。
2423

2524
## 快速使用
2625

@@ -83,11 +82,13 @@ Abracadabra 还在积极开发中,这里是一些注意事项。
8382
8483
#### 处理文件耗时指数级增加
8584
86-
密文选取的随机性导致了此问题
85+
项目目前使用的 JSON 解析库存在性能问题,特别是在执行大量枚举时
8786
88-
原则上不能以牺牲随机性为代价换取执行速度,且本项目之目的并不是将文件转换为上百万个汉字,故搁置该问题。
87+
本项目之目的并不是将文件转换为上百万个汉字,故搁置该问题。
8988
90-
小于 100kb 的文件均能在可控时间内得到处理。
89+
小于 100kb 的文件均能在可控时间内得到处理。大文件用 Node.js 处理更加高效,但解密可能导致浏览器卡死。
90+
91+
此问题将在未来积极解决。
9192
9293
#### 密本随机性不足
9394

src/abracadabra.cpp

Lines changed: 53 additions & 167 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <codecvt>
77
#include <random>
88
#include <Windows.h>
9+
#include <ctime>
910
#include <nlohmann/json.hpp>
1011
#include <cppcodec/base64_rfc4648.hpp>
1112
#include <CLI11.hpp>
@@ -27,6 +28,10 @@ const string SIG_BASE64 = "奂込,妍桜,姾凪,娂辺,奂飴,妍仮,姾実,娂
2728
const string SIG_DECRYPT = "飞込,电桜,亖凪,冇辺,亖飴,电仮,飞実,冇雫,亖気,电抜,飞杁";//加密字符串的标志位列表
2829
const string NULL_STR = ""; //默认忽略的占位字符,一个生僻字。
2930

31+
random_device rd;
32+
mt19937 generator(rd());
33+
uniform_int_distribution<int> distribution(0, 10000);
34+
3035
struct PreCheckResult { // 专门用来打包传递预检的结果
3136
string output;
3237
bool isUnNormal = false; // 判断是否含有特殊符号(表外内容)
@@ -47,16 +52,16 @@ DemapResult deMap(PreCheckResult input);
4752
string FindOriginText(string letter);
4853
string GetCryptedText(string letter);
4954
string GetLinkCryptedText(string text);
55+
int GetRandomIndex(int length);
5056
string UrlEncode(const string& szToEncode);
51-
string UrlDecode(const string& szToDecode);
5257
std::string GbkToUtf8(const char* src_str);
5358
std::vector<BYTE> readFile(const char* filename);
5459
PreCheckResult preCheck(string input);
5560

5661

5762
int main(int argc, char *argv[]){
5863
SetConsoleOutputCP(CP_UTF8); //注意,由于使用了Windows.h,这个版本仅能在Windows平台使用。
59-
CLI::App app{"***Abracadabra v0.2.1***"}; //CLI11提供的命令行参数解析
64+
CLI::App app{"***Abracadabra v0.2.5***"}; //CLI11提供的命令行参数解析
6065

6166
string arg1 = "";
6267
PreCheckResult input;
@@ -65,8 +70,8 @@ int main(int argc, char *argv[]){
6570
string::size_type idx;
6671
ofstream outfile;
6772
vector<BYTE> inputfiledata;
68-
6973

74+
7075
//定义命令行参数
7176
CLI::Option* i2flag = app.add_option("DEFAULT", i2, "Input text, if there is no given option besides.");
7277
CLI::Option* lflag = app.add_flag("-l", l, "Force to encrypt using url mode");
@@ -312,25 +317,14 @@ string enMap(PreCheckResult input,bool forceLink,bool forceBase64,bool forceDire
312317
forceBase64 = true;
313318
}
314319
int size = OriginStr.length();
320+
315321
for(int i=0;i<size;){
316322
int cplen = 1; //该死的C++,处理中文字符贼繁琐
317-
int cplen2 = 1;
318323
if((OriginStr[i] & 0xf8) == 0xf0) cplen = 4;
319324
else if((OriginStr[i] & 0xf0) == 0xe0) cplen = 3;
320325
else if((OriginStr[i] & 0xe0) == 0xc0) cplen = 2;
321326
if((i + cplen) > OriginStr.length()) cplen = 1;
322-
323-
if((OriginStr[i+cplen] & 0xf8) == 0xf0) cplen2 = 4;
324-
else if((OriginStr[i+cplen] & 0xf0) == 0xe0) cplen2 = 3;
325-
else if((OriginStr[i+cplen] & 0xe0) == 0xc0) cplen2 = 2;
326-
if((i + cplen + cplen) > OriginStr.length()) cplen2 = 1;
327327
temp = OriginStr.substr(i, cplen);
328-
if(i != size - cplen2){ //一次遍历两个字符,遇到倒数第一个的时候防止越界
329-
temp2 = OriginStr.substr(i+cplen, cplen2);
330-
}else{
331-
temp2 = NULL_STR;
332-
}
333-
group = temp + temp2;
334328

335329
//到这儿循环的取字部分就完成了
336330
//temp是前一个字,temp2是后一个字
@@ -345,13 +339,7 @@ string enMap(PreCheckResult input,bool forceLink,bool forceBase64,bool forceDire
345339
TempStr1 = TempStr1 + GetCryptedText(temp); //把加密字符加到结果字符串的后面
346340
i += cplen;
347341
}
348-
349342
//第一个循环结束后,TempStr1应当是完全的密文,但是缺少标志位
350-
//随机选择一个下标
351-
random_device rd;
352-
unsigned int seed = rd();
353-
mt19937 mt_r(seed);
354-
uniform_int_distribution<long long> dist(1, 10000);
355343
int RandIndex,RandIndex2;
356344
vector<int> Avoid;
357345
for(int q=0;q<2;q++){//分两次大循环
@@ -372,78 +360,40 @@ string enMap(PreCheckResult input,bool forceLink,bool forceBase64,bool forceDire
372360
i += cplen;
373361
PosToInset.push_back(i);
374362
}
375-
vector<string> CipherArray,CipherArray2;
376363
int i;
377364
if(q==0){//第一次大循环插入模式标志位
378-
RandIndex = PosToInset.at(dist(mt_r) % PosToInset.size());//在所有可插入位置中随便选一个
365+
RandIndex = PosToInset.at(GetRandomIndex(PosToInset.size()));//在所有可插入位置中随便选一个
379366
if(forceDirect){//无处理特殊字符标志位
380-
Map_Obj["special"]["TYPE"]["NORMAL"].get_to(CipherArray);
381-
RandIndex2 = dist(mt_r) % CipherArray.size();//随机获取一个下标
382-
i = 0;
383-
for (auto el : Map_Obj["special"]["TYPE"]["NORMAL"]){//遍历列表
384-
if(i == RandIndex2){
385-
TempStr1.insert(RandIndex,(string)el);
386-
string stemp = (string)el;
387-
for(int z = RandIndex + 1;z < RandIndex + stemp.length();z++){
388-
Avoid.push_back(z);
389-
}
390-
break;
391-
}
392-
i++;
393-
}
367+
RandIndex2 = GetRandomIndex(Map_Obj["special"]["TYPE"]["NORMAL"].size());//随机获取一个下标
368+
string stemp = (string)Map_Obj["special"]["TYPE"]["NORMAL"][RandIndex2];
369+
TempStr1.insert(RandIndex,stemp);
370+
for(int z = RandIndex + 1;z < RandIndex + stemp.length();z++){
371+
Avoid.push_back(z);
372+
}
394373
}else if(forceLink){ //链接模式标志位
395-
Map_Obj["special"]["TYPE"]["LINK"].get_to(CipherArray);
396-
RandIndex2 = dist(mt_r) % CipherArray.size();//随机获取一个下标
397-
i = 0;
398-
for (auto el : Map_Obj["special"]["TYPE"]["LINK"]){//遍历列表
399-
if(i == RandIndex2){
400-
TempStr1.insert(RandIndex,(string)el);
401-
string stemp = (string)el;
402-
for(int z = RandIndex + 1;z < RandIndex + stemp.length();z++){
403-
Avoid.push_back(z);
404-
}
405-
break;
406-
}
407-
i++;
408-
}
374+
RandIndex2 = GetRandomIndex(Map_Obj["special"]["TYPE"]["LINK"].size());//随机获取一个下标
375+
string stemp = (string)Map_Obj["special"]["TYPE"]["LINK"][RandIndex2];
376+
TempStr1.insert(RandIndex,stemp);
377+
for(int z = RandIndex + 1;z < RandIndex + stemp.length();z++){
378+
Avoid.push_back(z);
379+
}
409380
}else if(forceBase64){ //Base64模式标志位
410-
Map_Obj["special"]["TYPE"]["BASE64"].get_to(CipherArray);
411-
RandIndex2 = dist(mt_r) % CipherArray.size();//随机获取一个下标
412-
i = 0;
413-
for (auto el : Map_Obj["special"]["TYPE"]["BASE64"]){//遍历列表
414-
if(i == RandIndex2){
415-
TempStr1.insert(RandIndex,(string)el);
416-
string stemp = (string)el;
417-
for(int z = RandIndex + 1;z < RandIndex + stemp.length();z++){
418-
Avoid.push_back(z);
419-
}
420-
break;
421-
}
422-
i++;
423-
}
381+
RandIndex2 = GetRandomIndex(Map_Obj["special"]["TYPE"]["BASE64"].size());//随机获取一个下标
382+
string stemp = (string)Map_Obj["special"]["TYPE"]["BASE64"][RandIndex2];
383+
TempStr1.insert(RandIndex,stemp);
384+
for(int z = RandIndex + 1;z < RandIndex + stemp.length();z++){
385+
Avoid.push_back(z);
386+
}
424387
}
425388
}
426389
else if(q==1){ // 第二次大循环插入加密标志位
427-
428-
429390
vector<int> AvailPos;
430391
AvailPos.resize(max(PosToInset.size(),Avoid.size()));
431-
432392
vector<int>::iterator itEnd = set_difference(PosToInset.begin(), PosToInset.end(), Avoid.begin(), Avoid.end(), AvailPos.begin());
433-
434393
AvailPos.erase(std::remove(AvailPos.begin(), AvailPos.end(), 0), AvailPos.end());
435-
RandIndex = AvailPos.at(dist(mt_r) % AvailPos.size());//在所有可插入位置中随便选一个
436-
437-
Map_Obj["special"]["TYPE"]["DECRYPT"].get_to(CipherArray2);
438-
RandIndex2 = dist(mt_r) % CipherArray2.size();//随机获取一个下标
439-
i = 0;
440-
for (auto el : Map_Obj["special"]["TYPE"]["DECRYPT"]){//遍历列表
441-
if(i == RandIndex2){
442-
TempStr1.insert(RandIndex,(string)el);
443-
break;
444-
}
445-
i++;
446-
}
394+
RandIndex = AvailPos.at(GetRandomIndex(AvailPos.size()));//在所有可插入位置中随便选一个
395+
RandIndex2 = GetRandomIndex(Map_Obj["special"]["TYPE"]["DECRYPT"].size());//随机获取一个下标
396+
TempStr1.insert(RandIndex,(string)Map_Obj["special"]["TYPE"]["DECRYPT"][RandIndex2]);
447397
}
448398
}
449399

@@ -453,7 +403,6 @@ string enMap(PreCheckResult input,bool forceLink,bool forceBase64,bool forceDire
453403
DemapResult deMap(PreCheckResult input){
454404
string OriginStr = input.output;
455405
string TempStr1,TempStrz;
456-
457406
string temp,temp2,group,findtemp;
458407
string::size_type idx;
459408
int size = OriginStr.length();
@@ -550,28 +499,15 @@ DemapResult deMap(PreCheckResult input){
550499
string GetLinkCryptedText(string text){//查表,检查是否有任何预配置的关键词
551500
string s = text; //源文本
552501
string s1,s2;
553-
random_device rd;
554-
unsigned int seed = rd();
555-
mt19937 mt_r(seed);
556-
uniform_int_distribution<long long> dist(1, 10000);
557-
vector<string> CipherArray;
558502
int RandIndex;
559503

560504
for (auto& el : Map_Obj["link"].items()){//遍历关键词列表
561505
s1 = el.key();
562506
if(s.find(s1) != string::npos){//找到关键词
563-
el.value().get_to(CipherArray);
564507
while(s.find(s1)<s.size()){
565508
//返回密本中的随机字符
566-
RandIndex = dist(mt_r) % CipherArray.size(); //随机获取一个下标
567-
int i = 0 ;
568-
for (auto it : Map_Obj["link"][s1]){
569-
if (i == RandIndex){//找到下标
570-
s2 = (string)it;
571-
break;
572-
}
573-
i++;
574-
}
509+
RandIndex = GetRandomIndex(el.value().size()); //随机获取一个下标
510+
s2 = (string)Map_Obj["link"][s1][RandIndex];
575511
int pos = s.find(s1);
576512
s.replace(pos, s1.size(), s2);
577513
}
@@ -583,87 +519,33 @@ string GetLinkCryptedText(string text){//查表,检查是否有任何预配置
583519

584520
}
585521
string GetCryptedText(string letter){//查表返回加密之后的字符串
586-
random_device rd;
587-
unsigned int seed = rd();
588-
mt19937 mt_r(seed);
589-
uniform_int_distribution<long long> dist(1, 10000);
590-
591-
string::size_type idx,idx2,idx3,idx4;
592522
int RandIndex,RandIndex2;
593-
594-
idx = LETTERS.find(letter); //是否是小写字母
595-
idx2 = BIG_LETTERS.find(letter); //是否是大写字母
596-
idx3 = NUMBERS.find(letter); //是否是数字
597-
idx4 = SYMBOLS.find(letter); //是否是符号
598-
599-
if(idx != string::npos || idx2 != string::npos){//判断给定字符的类型
600-
string key,keyU;
523+
if(LETTERS.find(letter) != string::npos || BIG_LETTERS.find(letter) != string::npos){//判断给定字符的类型
601524
for (auto& el : Map_Obj["basic"]["alphabet"].items())
602-
{
603-
vector<string> CipherArray;
604-
vector<string> CipherArrayBIG;
605-
key = el.key();
606-
keyU = (string)key;
607-
if(key == letter){
608-
el.value().get_to(CipherArray); //把密本存进容器里
609-
RandIndex = dist(mt_r) % CipherArray.size(); //随机获取一个下标
610-
int i = 0 ;
611-
for (auto it : Map_Obj["basic"]["alphabet"][letter]){
612-
if (i == RandIndex){
613-
return (string)it;
614-
}
615-
i++;
616-
}
617-
}else if(strupr((char*)keyU.c_str()) == letter){//碰到大写字母
618-
el.value().get_to(CipherArray);
619-
Map_Obj["special"]["BIG"].get_to(CipherArrayBIG);
620-
RandIndex = dist(mt_r) % CipherArray.size();
621-
RandIndex2 = dist(mt_r) % CipherArrayBIG.size();
622-
int i = 0;
623-
for (auto it : Map_Obj["basic"]["alphabet"][key]){
624-
if (i == RandIndex){//选中小写字符的密文
625-
int t=0;
626-
for (auto tt : Map_Obj["special"]["BIG"]){
627-
if(t == RandIndex2){//随机选一个大写标志位
628-
return (string)tt + (string)it; //组合标志位和小写字符密文,返回回去
629-
}
630-
t++;
631-
}
632-
}
633-
i++;
634-
}
525+
{
526+
if(el.key() == letter){
527+
RandIndex = GetRandomIndex(el.value().size()); //随机获取一个下标
528+
return Map_Obj["basic"]["alphabet"][letter][RandIndex];
529+
}else if(letter[0] == toupper(el.key()[0])){//碰到大写字母
530+
RandIndex = GetRandomIndex(el.value().size());
531+
RandIndex2 = GetRandomIndex(Map_Obj["special"]["BIG"].size());
532+
return (string)Map_Obj["special"]["BIG"][RandIndex2] + (string)Map_Obj["basic"]["alphabet"][el.key()][RandIndex];
635533
}
636534
}
637-
}else if(idx3 != string::npos){
535+
}else if(NUMBERS.find(letter) != string::npos){
638536
for (auto& el : Map_Obj["basic"]["number"].items())
639537
{
640-
vector<string> CipherArray;
641-
if(el.key() == letter){
642-
el.value().get_to(CipherArray); //把密本存进容器里
643-
RandIndex = dist(mt_r) % CipherArray.size(); //随机获取一个下标
644-
int i = 0 ;
645-
for (auto it : Map_Obj["basic"]["number"][letter]){
646-
if (i == RandIndex){
647-
return it;
648-
}
649-
i++;
538+
if(el.key() == letter){
539+
RandIndex = GetRandomIndex(el.value().size()); //随机获取一个下标
540+
return Map_Obj["basic"]["number"][letter][RandIndex];
650541
}
651542
}
652-
}
653-
}else if(idx4 != string::npos){
543+
}else if(SYMBOLS.find(letter) != string::npos){
654544
for (auto& el : Map_Obj["basic"]["symbol"].items())
655545
{
656-
vector<string> CipherArray;
657546
if(el.key() == letter){
658-
el.value().get_to(CipherArray); //把密本存进容器里
659-
RandIndex = dist(mt_r) % CipherArray.size(); //随机获取一个下标
660-
int i = 0 ;
661-
for (auto it : Map_Obj["basic"]["symbol"][letter]){
662-
if (i == RandIndex){
663-
return it;
664-
}
665-
i++;
666-
}
547+
RandIndex = GetRandomIndex(el.value().size()); //随机获取一个下标
548+
return Map_Obj["basic"]["symbol"][letter][RandIndex];
667549
}
668550
}
669551
}
@@ -778,4 +660,8 @@ std::vector<BYTE> readFile(const char* filename)
778660
// read the data:
779661
return std::vector<BYTE>((std::istreambuf_iterator<char>(file)),
780662
std::istreambuf_iterator<char>());
663+
}
664+
inline int GetRandomIndex(int length){
665+
int Rand = distribution(generator);
666+
return Rand % length;
781667
}

0 commit comments

Comments
 (0)