2019全国大学生信息安全竞赛crypto---------part_des

呼~~这个题目让我重新弄了一遍DES加密与解密,然后遇到一个问题卡了好久好久。。。。。。。/好惭愧

嗯。。。。 话不多说,咱们开始吧!

首先拿到题目!!

Round n part 就是经过了DES加密n轮之后的密文,把Keymap里192位十六进制转化为二进制一共有768位,恰好768=16*48,这就是每轮的子密钥。
所以…子密钥都给了,密文也给了,我们就直接来敲代码啦!

咳咳咳,首先当然要了解DES的加密与解密啦,我就简短的来说一下吧。2019全国大学生信息安全竞赛crypto---------part_des_第1张图片
首先输入64位密钥,经过一系列操作生成子密钥。然后输入二进制明文,进行IP置换,分成三十二位L和R。L和R进行十六轮迭代操作。
2019全国大学生信息安全竞赛crypto---------part_des_第2张图片由图可知,每轮的结构都是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
    }

嗯。。。然后我暂时还不会输出字符串的操作。。我只会输出二进制和十六进制,所以就不展示啦!

嗯,这题大概就是这样了,最后附上运行结果!
2019全国大学生信息安全竞赛crypto---------part_des_第3张图片
2019全国大学生信息安全竞赛crypto---------part_des_第4张图片

flag{y0ur9Ood}

你可能感兴趣的:(原题复现)