Decrypt(HDU-3733)


1 题意

  将某个ASCII码文本用如下算法加密。

for(int i=0;i<contentLength;i+=keyLength){
    for(int j=0;j<keyLength&&i+j<contentLength;j++){
        fprintf(f,"%.2x",content[i+j]^key[j]);
    }
}

  加密后的密文如下。现要求通过密文得出原文。

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

  链接:link


2 思路

  从加密算法可以看出,其利用一个密文序列 k e y key key异或加密一个ASCII文件 c o n t e n t content content,并将加密后的ASCII字符按两位十六进制输出(一个ASCII码用8位表示,对应两个十六进制位)。

2.1 将密文还原为十进制

  为了更便于处理,现将十六进制密文转化为十进制,并用空格隔开每个密文字符。

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

2.2 推测密钥的头几个字符

  一般来说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"

2.3 推测密钥的长度

  以"XiaoHouZ"为模板暴力异或,找出第一个有意义的字符串。

2.3.1 代码

#include<iostream>
#include<cstdio>
#include<string>
#include<cctype>
using namespace std;
int content[]={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};
int main(){
    string key="XiaoHouZ";
    for(int i=0;i<=391-key.size();i++){
        cout<<"|"<<i+1<<"|";
        string str;
        for(int j=0;j<key.size();j++){
            printf("%d",content[i+j]^key[j]);
            if(j!=key.size()-1) cout<<" ";
            else cout<<"|";
            str.push_back(content[i+j]^key[j]);
        }
        for(auto c:str){
            if(!isprint(c)){
                cout<<"\\\\("<<oct<<int(c)<<dec<<")";
            }else{
                cout<<c;
            }
        }
        cout<<"|"<<endl;
    }
}

2.3.2 结果

i十进制表示字符表示(非可打印字符用转义字符表示)
135 105 110 99 108 117 100 101#include
288 102 109 75 82 126 74 19XfmKR~J\(23)
387 101 69 117 89 80 60 87WeEuYP<W
484 77 123 126 119 38 120 25TM{~w&x\(31)
5124 115 112 80 1 98 54 104
666 120 94 38 69 44 71 91Bx^&E,G[
773 86 40 98 11 93 116 93IV(b\(13)]t]
8103 32 108 44 122 110 114 113g l,znrq
917 100 34 93 73 104 94 17\(21)d"]Ih^\(21)
1085 42 83 110 79 68 62 126U*SnOD>~
1127 91 96 104 99 36 81 5\(33)[`hc$Q\(5)
12106 104 102 68 3 75 42 62jhfD\(3)K*>
1389 110 74 36 108 48 17 84YnJ$l0\(21)T
1495 66 42 75 23 11 123 123_B*K\(27)\(13){{
15115 34 69 48 44 97 84 92s"E0,aT\
1619 77 62 11 70 78 115 0\(23)M>\(13)FNs\(0)
17124 54 5 97 105 105 47 111
187 13 111 78 78 53 64 82\(7)\(15)oNN5@R
1960 103 64 105 18 90 125 82<g@i\(22)Z}R
2086 72 103 53 125 103 125 91VHg5}g}[
21121 111 59 90 64 103 116 58yo;Z@gt:
2294 51 84 103 64 110 21 28^3Tg@n\(25)\(34)
232 92 105 103 73 15 51 15\(2)\igI\(17)3\(17)
24109 97 105 110 40 41 32 123main() {
2580 97 96 15 14 58 84 57Pa`\(17)\(16):T9
2680 104 1 41 29 78 22 98Ph\(1))\(35)N\(26)b
2789 9 39 58 105 12 77 12Y\(11)’:i\(14)M\(14)
2856 47 52 78 43 87 35 1158/4N+W#s
2930 60 64 12 112 57 92 77\(36)<@\(14)p9\M
3013 72 2 87 30 70 98 28\(15)H\(2)W\(36)Fb\(34)
31121 10 89 57 97 120 51 119y\(12)Y9ax3w
3259 81 55 70 95 41 88 81;Q7F_)XQ
3396 63 72 120 14 66 126 98`?Hx\(16)B~b
3414 64 118 41 101 100 77 27\(16)@v)edM\(33)
35113 126 39 66 67 87 52 93q~'BCW4]
3679 47 76 100 112 46 114 0O/Ldp.r\(0)
3730 68 106 87 9 104 47 37\(36)DjW\(11)h/%
38117 98 89 46 79 53 10 19ubY.O5\(12)\(23)
3983 81 32 104 18 16 60 73SQ h\(22)\(20)<I
4096 40 102 53 55 38 102 35`(f57&f#
4125 110 59 16 1 124 12 14\(31)n;\(20)\(1)
4295 51 30 38 91 22 33 10_3\(36)&[\(26)!\(12)
432 22 40 124 49 59 37 5\(2)\(26)(
4439 32 114 22 28 63 42 34’ r\(26)\(34)?*"
4517 122 24 59 24 48 13 14\(21)z\(30);\(30)0\(15)\(16)
4675 16 53 63 23 23 33 70K\(20)5?\(27)\(27)!F
4733 61 49 48 48 59 105 43!=100;i+
4812 57 62 23 28 115 4 24\(14)9>\(27)\(34)s\(4)\(30)
498 54 25 59 84 30 55 66\(10)6\(31);T\(36)7B
507 17 53 115 57 45 109 17\(7)\(21)5s9-m\(21)

2.3.3 结论

  当 i = 24 i=24 i=24时,出现"main() {"这几个字符,得知密钥长度为23。

2.4 推测密钥的剩余部分

  “main() {“之前应该是"int “,所以密钥的末尾四个字符为"gOrz”。
  此时中间还差了 11 11 11个字符,推测中间的明文为” <stdio.h>\n”,进而得到中间的密钥为"i10FenDeLan"
综上key值为"XiaoHouZi10FenDeLangOrz"。

2.5 利用密钥破译密文

2.5.1 代码

#include<iostream>
#include<cstdio>
using namespace std;
int content[]={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};
int main(){
    char key[]="XiaoHouZi10FenDeLangOrz";
    for(int i=0;i<391;i+=23){
        for(int j=0;j<23&&i+j<391;j++){
            printf("%c",content[i+j]^key[j]);
        }
    }
}

2.5.2 解密结果

#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;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值