呼~~这个题目让我重新弄了一遍DES加密与解密,然后遇到一个问题卡了好久好久。。。。。。。/好惭愧
嗯。。。。 话不多说,咱们开始吧!
首先拿到题目!!
Round n part 就是经过了DES加密n轮之后的密文,把Keymap里192位十六进制转化为二进制一共有768位,恰好768=16*48,这就是每轮的子密钥。
所以…子密钥都给了,密文也给了,我们就直接来敲代码啦!
咳咳咳,首先当然要了解DES的加密与解密啦,我就简短的来说一下吧。
首先输入64位密钥,经过一系列操作生成子密钥。然后输入二进制明文,进行IP置换,分成三十二位L和R。L和R进行十六轮迭代操作。
由图可知,每轮的结构都是L[i]=R[i-1],R[i]=L[i-1]^F(R[i-1],K[i]),然后经过16轮相同的操作之后,将L和R互换,再经过IP逆置换得到密文。
密文解密的方法也和原来差不多,但是自己要想的很明白才行,其他地方讲的都挺笼统的。
一般来说,解密就是逆着回去推。按照这种思路的话,(假设子密钥都已知)我们要先将密文IP置换(逆置换再逆过来就是置换),再进行32位置换。接着,根据之前的每轮结构,我们能推出解密的结构为
R[i-1]=L[i];
L[i-1]=R[i]^F(R[i-1],K[i]);
(此时子密钥是从K16到K1逆过来用)
最后在进行IP逆置换就能得到明文了。
但其实,解密的每轮结构与原来加密的每轮结构近乎一样,唯一的区别只在于L和R的位置。所以,我们可以直接利用原来的加密算法,直接IP置换,(不用再LR置换了)将L,R代入加密算法中去,只不过将每轮密钥换成从K16到K1而已。最后才进行LR置换,再IP逆置换,得到明文。
好了,说回原题。该题就是让我们另类解密。有了上面的操作,大家理应对解密很熟悉了,而本题并未告诉我们n是多少,所以我们把n从1到16都试一遍。首先,题目中的密文是n轮之后的结果,没有LR置换,也没有IP逆置换,我们可以直接来推解密函数。(就是我上面的内两行)
R[i-1]=L[i];
L[i-1]=R[i]^F(R[i-1],K[i]);
直接使用,但要注意子密钥的顺序,是从大到小。
(例如n为 6,则子密钥K[i]的顺序为K6,K5…K1)
将该结构进行n次,然后再逆置换就得到结果啦!
(n有16种情况噢,要循环16次!)
最后将输出的值都化为字符串就行啦!(二进制转字符串或者十六进制转字符串)
tips:注意每次n的循环开始都要重新给L数组和R数组赋值!!!(我就栽了跟头!)
int Key[16][48]={
{1,1,1,0,0,0,0,0,1,0,1,1,1,1,1,0,0,1,1,0,0,1,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,1,0,1,1,0,1,0,1,0,1},
{1,1,1,1,0,0,0,0,1,0,1,1,0,1,1,0,0,1,1,1,0,1,1,0,1,1,1,1,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,1,0,1,0,1},
{1,1,1,0,0,1,0,0,1,1,0,1,0,1,1,0,0,1,1,1,0,1,1,0,0,0,1,0,0,0,1,1,0,1,1,0,0,0,1,0,1,0,0,0,1,1,1,1},
{1,1,1,0,0,1,1,0,1,1,0,1,0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,1,0,1,1,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,1,1},
{1,0,1,0,1,1,1,0,1,1,0,1,0,0,1,1,0,1,1,1,0,0,1,1,1,0,1,0,0,1,1,0,0,0,0,0,0,0,0,1,0,1,1,0,0,1,1,1},
{1,0,1,0,1,1,1,1,0,1,0,1,0,0,1,1,0,1,1,1,1,0,1,1,0,1,0,0,0,1,1,0,1,0,1,0,1,0,1,1,1,1,0,0,0,0,1,0},
{1,0,1,0,1,1,1,1,0,1,0,1,0,0,1,1,1,1,0,1,1,0,0,1,0,1,1,1,0,1,0,0,1,0,0,0,0,1,0,1,0,1,0,1,1,0,0,1},
{0,0,0,1,1,1,1,1,0,1,0,1,1,0,1,1,1,1,0,1,1,0,0,1,0,1,0,0,1,0,1,1,1,0,0,1,0,1,0,0,0,1,0,0,1,0,1,0},
{0,0,1,1,1,1,1,1,0,1,0,0,1,0,0,1,1,1,0,1,1,0,0,1,0,1,0,0,1,0,0,0,1,0,0,1,0,1,1,1,1,1,1,0,1,0,1,0},
{0,0,0,1,1,1,1,1,0,1,1,0,1,0,0,1,1,0,0,1,1,1,0,1,0,0,0,1,1,1,0,0,1,1,0,1,1,1,0,0,0,0,1,0,1,0,0,1},
{0,0,0,1,1,1,1,1,0,0,1,0,1,1,0,1,1,0,0,1,1,1,0,1,0,1,0,0,1,0,1,0,0,1,0,1,1,1,0,0,0,1,1,1,0,0,0,0},
{0,1,0,1,1,1,1,1,0,0,1,0,1,1,0,0,1,0,1,0,1,1,0,1,1,0,0,0,1,0,0,1,1,1,1,0,1,0,0,1,0,0,1,1,1,0,0,0},
{1,1,0,1,1,0,1,1,1,0,1,0,1,1,0,0,1,0,1,0,1,1,0,0,1,0,1,0,0,0,0,1,0,1,0,1,1,1,1,0,0,0,0,1,0,0,0,0},
{1,1,0,1,1,0,0,0,1,0,1,0,1,1,1,0,1,0,1,0,1,1,1,0,1,1,0,1,1,0,0,1,0,0,0,0,0,0,1,0,0,0,1,1,0,1,1,0},
{1,1,1,1,0,0,0,0,1,0,1,1,1,1,1,0,0,0,1,0,1,1,1,0,1,0,0,1,0,1,0,1,0,1,0,0,1,0,1,0,1,0,0,0,1,1,0,0},
{1,1,1,1,0,0,0,0,1,0,1,1,1,1,1,0,1,0,1,0,0,1,1,0,0,0,0,1,0,0,0,1,0,0,1,0,1,1,1,0,1,0,0,0,0,1,0,0}
};
int Message[64]={1,0,0,1,0,0,1,0,1,1,0,1,1,0,0,1,0,0,0,1,0,1,0,1,0,0,1,0,0,1,0,1,0,0,0,0,0,0,0,1,0,0,0,1,1,0,0,1,1,1,1,0,0,0,0,1,0,0,1,0,1,0,1,1};
这是我手撸的数组。。。。
代码只给关键部分噢!
记得把LR赋值的语句都放在n里面!
for(n=0;n<16;n++)
{printf("\n第%d次:",n+1);
for(i=0;i<64;i++)//The location is important!!!!!!!!!!!!!!!!!!!!!!!
if(i<32)
L1[i]=Message[i];
else
R1[i-32]=Message[i];
每轮函数
for(i=0;i<=n;i++)
{
for(j=0;j<48;j++)
K2[j]=Key[n-i][j];//get baby key
for(j=0;j<32;j++)
R2[j]=R1[j];//store R
for(j=0;j<32;j++)
R1[j]=L1[j];//update R
Feistel(L1,K2,F);
for(j=0;j<32;j++)
{
L1[j]=F[j]^R2[j];}//update L
}
嗯。。。然后我暂时还不会输出字符串的操作。。我只会输出二进制和十六进制,所以就不展示啦!
flag{y0ur9Ood}