您的位置:首页 > 其它

Decrypt(加密解密)

2018-11-19 19:45 54 查看


我摘选的是南阳理工学院acm的题目(134题),这是改编自ACM_DIY群赛的一道题目。HDU3733有原版题目,不过只是加密代码有点差异。这道题的提交量极少,目前只有60多人提交,可能只有有把握的人才会提交,一般人看了题目之后就走了。其实我一个多月前就看了这道题目,一直不明白原理,cpp文件明明是ASCII码文件,怎么跟16进制扯上关系了?感觉题目很突兀,网上也没有任何题解(不知道为什么没有人写博客),总感觉如果没把这道题A过刷其他题都没有信心。后来无意在百度文库中找到了作者给出的题解,不过题解只有一句话:暴力破解。顺便把这句话贴在下面
16进制的加密码一共有782个字符,没有完全显示出来,我就直接贴在下面了

7b000f0c241a113f490d433201072b4b245f640e21065a35080801604655216338562917462d0b384
1075a7f49137954505f78541c7142184b4c6c67220a3e4907093b521065595a056952446a590a5a6
d4e473f6f456867012000523107154f2352456102100d77555e7f0e674a476d467b73636368663554
7f53143b1066454e6b4a18090b472c1d1e3d49030a2e00073f49584366101d210929121d4b6f1d143
4104109271d553307524223041d2d0b2b411a0f2a52163d07061b204f1a3c4945582f164e270a2804
406d6f525a78191306261b13724b615c23041d21453f140c0a26065a350c4d4f3c07103449485f334
5192d09204109023b523b1b495b4261331b78400a3a66454e64153e080013295a580c01044f230a0
c7a0042101e0c0f2b2d2314340e7e423c3d07250a040e1b3d26434a1a0b4c6d5e46414e476f5d550
c01044f291a0132064343660a08641124081d473f00153a0504026855553600524332041c6404220
54e0320001b3d040e0127047f7a49111034001a311722415e5c450f70

昨晚又重新看了这道题目灵感突发,我直接把输出格式%.2x拎了出来,发现这是控制输出两位16进制数的格式,如果不足以为在前面补零,但是超过两位不做截取,比如15输出的是0f,256输出的是100。而两位16进制数刚好对应8位,也就对应一个ASCII码。之后我就明白了这个16进制代码的含义了。两个ASCII码做异或运算最多不超过两位16进制代码,如果用16进制存储会大大减少编码长度。以二为单位对这个16进制代码进行划分,将其解释为ASCII码(由于某些字符不能显示,所以用整数表示)

123 0 15 12 36 26 17 63 73 13 67 50 1 7 43 75 36 95 100 14 33 6 90 53 8 8 1 96 70 85 33 99 56
86 41 23 70 45 11 56 65 7 90 127 73 19 121 84 80 95 120 84 28 113 66 24 75 76 108 103 34 10 62
73 7 9 59 82 16 101 89 90 5 105 82 68 106 89 10 90 109 78 71 63 111 69 104 103 1 32 0 82 49 7
21 79 35 82 69 97 2 16 13 119 85 94 127 14 103 74 71 109 70 123 115 99 99 104 102 53 84 127
83 20 59 16 102 69 78 107 74 24 9 11 71 44 29 30 61 73 3 10 46 0 7 63 73 88 67 102 16 29 33 9
41 18 29 75 111 29 20 52 16 65 9 39 29 85 51 7 82 66 35 4 29 45 11 43 65 26 15 42 82 22 61 7 6
27 32 79 26 60 73 69 88 47 22 78 39 10 40 4 64 109 111 82 90 120 25 19 6 38 27 19 114 75 97 92
35 4 29 33 69 63 20 12 10 38 6 90 53 12 77 79 60 7 16 52 73 72 95 51 69 25 45 9 32 65 9 2 59 82
59 27 73 91 66 97 51 27 120 64 10 58 102 69 78 100 21 62 8 0 19 41 90 88 12 1 4 79 35 10 12
122 0 66 16 30 12 15 43 45 35 20 52 14 126 66 60 61 7 37 10 4 14 27 61 38 67 74 26 11 76 109
94 70 65 78 71 111 93 85 12 1 4 79 41 26 1 50 6 67 67 102 10 8 100 17 36 8 29 71 63 0 21 58 5 4
2 104 85 85 54 0 82 67 50 4 28 100 4 34 5 78 3 32 0 27 61 4 14 1 39 4 127 122 73 17 16 52 0 26
49 23 34 65 94 92 69 15 112

下面我们要探寻的就是key值,也就是密钥,根据题目的加密过程,我们可以将加密后的代码与key值异或回去就可以得到源代码。我理解到这个程度几乎是一个重大的突破。这个ASCII码表就是我的解题基础。昨天晚上由于题目理解错了,key值一直没有破解,今天早上问了一下熊学长,他说他没见过这个题目,我把我的思路讲给了他,他感到很茫然,不过对我这个思路还是持相信态度的。

想当年二战时期,图灵为了破解德国密码,自制计算机运转了两个月竟然破解出来了。这也极大地增加了我的信心。

下面我们进入正题吧!

一般来说cpp文件第一句话就是#include,我们将这几个字符与前几个加密码进行一一比较

ENC 123  0   15  12  36  26  17  63
ORI   #  i    n   c   l   u   d   e
ASC  23  69  110  63 108 75  64 65
KEY  58  69   61 111 48  111 75 90
ASC  X   i    a   o   H   o   u  Z

得出明文密钥第一部分"XiaoHouZ"

下面我们以这个密钥为基准找出,"main"字符这几个字符。搜索得到位置在24。得知密钥长度为23。

main之前应该是"int "所以可以得出后面四个字符为,“gorz”。

显然中间还差了11个字符,我们可以大胆猜测中间的代码应该为" <stdio.h>\n",按照如上的方式对key值一一对应进行匹配,得到中间的key值为"i10FenDeLan"

综上key值为"XiaoHouZi10FenDeLangorz"。

得到密钥之后,就可以开始解密了,我们将输出写在一个文件里。

#include<cstdio>
#include<iostream>
#include<string>
using namespace std;
int toint(char a)
{
if(a<='9')
return a-'0';
else
return a-'a'+10;
}
int main()
{
FILE*fp;
fp=fopen("1.txt","w");
string str="7b000f0c241a113f490d433201072b4b245f640e21065a35080801604655216338562917462d0
b3841075a7f49137954505f78541c7142184b4c6c67220a3e4907093b521065595a056952446a5
90a5a6d4e473f6f456867012000523107154f2352456102100d77555e7f0e674a476d467b736363
686635547f53143b1066454e6b4a18090b472c1d1e3d49030a2e00073f49584366101d21092912
1d4b6f1d1434104109271d553307524223041d2d0b2b411a0f2a52163d07061b204f1a3c4945582
f164e270a2804406d6f525a78191306261b13724b615c23041d21453f140c0a26065a350c4d4f3c
07103449485f3345192d09204109023b523b1b495b4261331b78400a3a66454e64153e0800132
95a580c01044f230a0c7a0042101e0c0f2b2d2314340e7e423c3d07250a040e1b3d26434a1a0b4
c6d5e46414e476f5d550c01044f291a0132064343660a08641124081d473f00153a050402685555
3600524332041c640422054e0320001b3d040e0127047f7a49111034001a311722415e5c450f70"
;
int k=0;
char a[391];
string key="XiaoHouZi10FenDeLangOrz";
for(int i=0;i<781;i+=2)
{
int x,y;
x=toint(str[i]);
y=toint(str[i+1]);
a[k++]=x*16+y;
}
for(int i=0;i<k;i+=key.length())
{
for(int j=0;j<key.length()&&i+j<k;j++)
{
fprintf(fp,"%c",a[i+j]^key[j]);
}
}
}

输出结果如下

#include <stdio.h>
int main() {
for(int i=0;i!=100;i++){
for(int j=0;j!=100;j++){
for(int k=0;k!=100;k++)
;
};
}
//The code before is useless, only for increasing the length of this code.
printf("Please submit me, then you will get AC :-)\n");
printf("The key is XiaoHouZi10FenDeLangOrz\n");
//The authors of this problem : licstar and doraemonok
return 0;
}

直接将这个代码贴上去就ac了,其中上面的三重循环是没有任何作用的,可以将其删掉。

说到这里你们以后也可以按照此方法对自己一些重要的代码加密,密钥设置的长一些别人就很难破解。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: