对FEAL-4的线性***

1. FEAL密码算法简介

FEAL密码算法家族是日本NTT(日本电报电话公司)的清水(Shimizi)和宫口(Miyaguchi)设计的(1986)。作为一种分组密码,与DES相比其主要想法为增加每一圈迭代的算法强度,因此可以通过减少迭代次数而提高运算速度。

FEAL-8即为8圈迭代的FEAL密码算法。FEAL密码算法推出之后,引起有关专家的注意。密码专家比哈姆和沙米尔利用差分密码分析技术发现,可以用比穷举法更快的速度破译FEAL密码。如FEAL-8只需2000个选择明文即可破译,而FEAL-4更只需8个精心选择的明文便可破译。

这个小密码系统用来做破译练手最合适不过了,本文对http://www.computing.dcu.ie/~mike/linear.html中的文章进行了学习,记录笔记如下。

2. FEAL密码算法结构

FEAL密码算法仅4圈,数据块为64位。最核心的便是轮函数f,输入、输出均32位。抗差分或线性分析均取决于此函数的设计。故用红色标出,其实Feistel结构本身的混淆是有限的。Feistel结构的优点是其轮函数可以是单向的,这样密码算法有更好的统计属性。而SPN网络的SBOX虽求逆困难,但不能单向,否则无法解密。

图1 FEAL密码结构

这里的密钥K0~K5均是从初始密钥K扩展而来,每个32位。而实际的***结果是完全攻破6*32=192位密钥。所以,密钥协商算法是单向的也没关系,可以把子密钥看做随机生成。

2.1 FEAL轮函数结构

图2 FEAL轮函数结构

轮函数的关键是非线性性,移位和异或都起到了这样的作用。输入为32位字,分为4个8位的小块。

3. FEAL密码算法线性***

线性***的本质是获得整个密码算法的线性表达式。可先分析轮函数的线性表达式,再分析整个密码算法的线性表达式。该表达式最终能化成只含明、密文及第1轮子密钥的式子。

a = S23,29(L0 Å R0 Å L4) Å S31(L0 Å L4 Å R4)Å S31F(L0 Å R0 Å K0)而a同时又可化为 a = S31(K1ÅK3ÅK4ÅK5) Å S23,29(K4) ,即该式子对任意明、密文应该为常数。于是可穷举K0的值去看a的值,若为常数,则可能获得正确的密钥。

3.1 轮函数中的线性表达式

直接贴来了,参见《Breaking Ciphers in the Real World》。本文省略了很多线性表达式由来的分析。

图3 轮函数中的线性表达式推导

由于轮函数的输入是32位,所以不可能像小SBOX一样,穷举所有差分。

3.2 整个密码算法的表达式推导

整个密码算法的线性表达式。该表达式最终能化成只含明、密文及第1轮子密钥的式子。a = S23,29(L0 Å R0 Å L4) Å S31(L0 Å L4 Å R4)Å S31F(L0 Å R0 Å K0)。而a同时又可化为  a = S31(K1ÅK3ÅK4ÅK5) Å S23,29(K4),这里一系列的变换参见《Breaking Ciphers in the Real World》

图4 整个密码算法

3.3 初始密钥k0的获取

穷举所有的K0的值,看a的值是否对n个明、密文对在特定的K0下全为常数,若是,则很有可能是正确的K0.本质上a只与密钥相关,密钥定了,值就定了。a = S23,29(L0 Å R0 Å L4) Å S31(L0 Å L4 Å R4)Å S31F(L0 Å R0 Å K0)

3.4 复杂度的进一步化简

实际在a表达式中真正用到的就12位:10~15,17~23,其它位并不参与a值得运算,所以先穷举出这12位,再同样的技巧分析其它位,最后穷举剩余的位会更为简洁。同样的技巧可用于K1~K5的分析。

4. 试验结果

使用了60个已知明文、密文。在穷举10~15,17~23下,共4096种可能。看哪一种会使60个明文、密文的式子a全为常数0或1,则视为正确密钥10~15,17~23。可能的密钥有几个,但仅一个是正确的。

5. 附录代码

注:代码中的a表达式用的是下面的,推导见http://www.computing.dcu.ie/~mike/linear.html

a=Ph[10,16,18,26] ÅPl[10,18,26] Å Ch[10,16,18,26] Å Cl[16] Å F(PhÅPl,K1)[16]  = K4[16,24] Å K6[10,18,26] Å K2[16,24]

  1. /*
  2. * The FEAL cipher - Linear Cryptanalysis
  3. */
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. /* uncomment this next statement to activate linear cryptanalysis code... */
  7. #define DEBUG
  8. #define WORD32 unsigned int
  9. #define BYTE unsigned char
  10. //循环左移技巧
  11. #define ROT2(x) (((x)<&lt;2) | ((x)>&gt;6))
  12. #define S0(a,b) (ROT2((BYTE)((a)+(b))))
  13. #define S1(a,b) (ROT2((BYTE)((a)+(b)+1)))
  14. //字节数组化字技巧
  15. static WORD32 pack32(BYTE *b)
  16. { /* pack 4 bytes into a 32-bit Word */
  17. return ((WORD32)b[3]<&lt;24)|((WORD32)b[2]&lt;&lt;16)|((WORD32)b[1]&lt;&lt;8)|(WORD32)b[0];
  18. }
  19. //字化字节数组技巧
  20. static void unpack32(WORD32 a,BYTE *b)
  21. { /* unpack bytes from a 32-bit word */
  22. b[0]=(BYTE)a;
  23. b[1]=(BYTE)(a>&gt;8);
  24. b[2]=(BYTE)(a&gt;&gt;16);
  25. b[3]=(BYTE)(a&gt;&gt;24);
  26. }
  27. WORD32 f(WORD32 x,WORD32 key)
  28. {
  29. BYTE f[4];
  30. BYTE k[4];
  31. unpack32(x,f);
  32. unpack32(key,k);
  33. f[2]^=(f[3]^k[2]);
  34. f[1]^=(f[0]^k[1]);
  35. f[2]=S1(f[2],f[1]);
  36. f[1]=S0(f[1],f[2]);
  37. f[3]=S0(f[3]^k[3],f[2]);
  38. f[0]=S1(f[0]^k[0],f[1]);
  39. /* printf("%02x%02x%02x%02x\n",f[3],f[2],f[1],f[0]); */
  40. return pack32(f);
  41. }
  42. /* H for High, L for Low */
  43. void feal_encrypt(BYTE data[8],WORD32 *key)
  44. {
  45. int i;
  46. WORD32 H,L,T;
  47. H=pack32(&data[4]);
  48. L=H^pack32(&data[0]);
  49. T=L;
  50. L=H^f(L,key[0]);
  51. H=T;
  52. T=L;
  53. L=H^f(L,key[1]);
  54. H=T;
  55. L^=key[4];
  56. H^=key[5];
  57. T=L;
  58. L=H^f(L,key[2]);
  59. H=T;
  60. T=L;
  61. L=H^f(L,key[3]);
  62. H=T;
  63. H^=L;
  64. unpack32(L,&data[4]);
  65. unpack32(H,&data[0]);
  66. }
  67. void feal_decrypt(BYTE data[8],WORD32 *key)
  68. {
  69. int i;
  70. WORD32 H,L,T;
  71. L=pack32(&data[4]);
  72. H=L^pack32(&data[0]);
  73. T=H;
  74. H=L^f(H,key[3]);
  75. L=T;
  76. T=H;
  77. H=L^f(H,key[2]);
  78. L=T;
  79. L^=key[4];
  80. H^=key[5];
  81. T=H;
  82. H=L^f(H,key[1]);
  83. L=T;
  84. T=H;
  85. H=L^f(H,key[0]);
  86. L=T;
  87. L^=H;
  88. unpack32(H,&data[4]);
  89. unpack32(L,&data[0]);
  90. }
  91. int main(int argc,char **argv)
  92. {
  93. int i,j,lhs,rhs;
  94. int Ph10161826,Pl101826,Ch10161826,Cl16,Ch16;
  95. BYTE input[10];
  96. BYTE data[8],k[4];
  97. WORD32 key[6],ph,pl,ch,cl,k1;
  98. BYTE bits[4096];
  99. int first_time_in=1;
  100. /* DELETED - Secret key generator. Sets keys key[0] ... key[5] */
  101. key[1]=key[2]=key[3]=key[4]=key[5]=0; /* not the real key ! */
  102. key[0]=0x2E3500; /* !! This is the first sub-key we find! */
  103. #ifndef DEBUG
  104. argc--; argv++;
  105. if (argc!=8)
  106. {
  107. printf("command line error - input 8 bytes of plaintext in hex\n");
  108. printf("For example:-\n");
  109. printf("findkey 0 1 2 3 4e 5a f6 37\n");
  110. return 0;
  111. }
  112. for (i=0;i<8;i++)
  113. sscanf(argv[i],"%x",&input[i]);
  114. for (i=0;i&lt;8;i++) data[i]=input[7-i];
  115. printf("Plaintext= ");
  116. for (i=7;i>=0;i--) printf("%02x ",data[i]);
  117. printf("\n");
  118. feal_encrypt(data,key);
  119. printf("Ciphertext= ");
  120. for (i=7;i&gt;=0;i--) printf("%02x ",data[i]);
  121. printf("\n");
  122. feal_decrypt(data,key);
  123. printf("Plaintext= ");
  124. for (i=7;i&gt;=0;i--) printf("%02x ",data[i]);
  125. printf("\n");
  126. #else
  127. for (i=0;i<8;i++) data[i]=(BYTE)rand();
  128. /*
  129. the debug code below searches through all k1[8~13] and k1[16~21],
  130. as described by Matsui. That's 4096 possibilities. It outputs a
  131. 0 or a 1 for each possible key.
  132. For all known plaintexts/ciphertexts the right key will always give the
  133. same fixed 0 or 1
  134. For each plaintext/ciphertext pair newly discovered wrong keys
  135. are replaced with an X
  136. */
  137. /* Now try for 60 random plaintexts... */
  138. for (j=0;j&lt;60;j++)
  139. {
  140. for (i=0;i&lt;8;i++) data[i]=(BYTE)rand(); /* random plaintexts */
  141. printf("\nPlaintext= ");
  142. for (i=7;i>=0;i--) printf("%02x ",data[i]);
  143. printf("\n");
  144. pl=pack32(&data[0]);
  145. ph=pack32(&data[4]);
  146. Ph10161826=((ph&gt;&gt;10)^(ph&gt;&gt;16)^(ph&gt;&gt;18)^(ph&gt;&gt;26))&1;
  147. Pl101826 =((pl&gt;&gt;10)^(pl&gt;&gt;18)^(pl&gt;&gt;26))&1;
  148. feal_encrypt(data,key);
  149. printf("Ciphertext= ");
  150. for (i=7;i&gt;=0;i--) printf("%02x ",data[i]);
  151. printf("\n");
  152. cl=pack32(&data[0]);
  153. ch=pack32(&data[4]);
  154. Ch10161826=((ch&gt;&gt;10)^(ch&gt;&gt;16)^(ch&gt;&gt;18)^(ch&gt;&gt;26))&1;
  155. Cl16=((cl&gt;&gt;16)&1);
  156. Ch16=((ch&gt;&gt;16)&1);
  157. for (i=0;i<4096;i++)
  158. {
  159. //无关的位置0,用到的&出来
  160. k[0]=0; k[1]=i&0x3F; k[2]=(i>&gt;6)&0x3F; k[3]=0;
  161. k1=pack32(k);
  162. lhs=(Ph10161826^Pl101826^Ch10161826^Cl16^(f(ph^pl,k1)&gt;&gt;16))&1;
  163. if (first_time_in) bits[i]=lhs;
  164. else if (lhs!=bits[i]) bits[i]=0xFF;
  165. }
  166. /* print out the 4096 bit array */
  167. for (i=0;i<4096;i++)
  168. {
  169. if (bits[i]==0xFF)
  170. {
  171. printf("X");
  172. continue;
  173. }
  174. printf("%d",bits[i]);
  175. }
  176. first_time_in=0;
  177. }
  178. printf("\nCandidates for bits 8-13, and 16-21 of key[0] are\n");
  179. for (i=0;i&lt;4096;i++)
  180. {
  181. if (bits[i]==0xFF) continue;
  182. k[0]=0; k[1]=i&0x3F; k[2]=(i>&gt;6)&0x3F; k[3]=0;
  183. k1=pack32(k);
  184. printf("%x\n",k1);
  185. }
  186. printf("Actual key[0] we were looking for = %x\n",key[0]);
  187. #endif
  188. return 0;
  189. }

转载于:https://blog.51cto.com/linuxcumt/709613

对FEAL-4的线性***相关推荐

  1. 数据结构(08)— 线性单链表基本操作

    1. 线性单链表数据结构 // 假定每个结点的类型用 SNode 表示 typedef struct SNodeTag {int data; // 所存储的数据元素SNodeTag *next; // ...

  2. 数据结构(07)— 线性顺序表基本操作

    1. 顺序表结构 #define MaxLen 50typedef struct {int data[MaxLen]; // 定义一个数组来存储线性表中所有元素int len; // 存储线性表的长度 ...

  3. 数据结构(05)— 线性单链表实战

    1. 设计思路 本项目的实质是完成对考生信息的建立.查找.插入.修改.删除等功能,可以首先定义项目的数据结构,然后将每个功能写成一个函数来完成对数据的操作,最后完成主函数以验证各个函数功能并得出运行结 ...

  4. 数据结构(04)— 线性顺序表实战

    1. 设计思路 本实战的实质是完成对学生成绩信息的建立.查找.插入.修改.删除等功能,可以首先定义项目的数据结构,然后将每个功能写成一个函数来完成对数据的操作,最后完成主函数以验证各个函数功能并得出运 ...

  5. leetcode 5. Longest Palindromic Substring 字符串中的最长回文数 逐步从O(n^2)优化至线性时间

    题目 解析 思路一 暴力解法 思路二 指针+最大长度 思路3 由中间至两边找回数 思路4 Manacher's algorithm 线性时间 参考文档 题目 链接 给定一个字符串 s,找到 s 中最长 ...

  6. 数据结构与算法——线性结构——线性表及其表示

    -"一,线性结构 1.顺序储存结构直接表示 多项式. 1).使用数组来表示多项式.(用数组下标来表示指数,值来表示系数) 可以表示成: 2).使用结构数组来表示.(把系数和指数看成一个二元组 ...

  7. 【Learning Notes】线性链条件随机场(CRF)原理及实现

    1. 概述 条件随机场(Conditional Random Field, CRF)是概率图模型(Probabilistic Graphical Model)与区分性分类( Discriminativ ...

  8. NVIDIA GPU上的直接线性求解器

    NVIDIA GPU上的直接线性求解器 NVIDIA cuSOLVER库提供了密集且稀疏的直接线性求解器和本征求解器的集合,它们为计算机视觉,CFD,计算化学和线性优化应用程序提供了显着的加速.cuS ...

  9. MegEngine亚线性显存优化

    MegEngine亚线性显存优化 MegEngine经过工程扩展和优化,发展出一套行之有效的加强版亚线性显存优化技术,既可在计算存储资源受限的条件下,轻松训练更深的模型,又可使用更大batch siz ...

最新文章

  1. 小程序中textarea层级最高的结局办法
  2. Sharding-JDBC(三)3.1.0版本实践
  3. Linux ENSP 搭建DHCP服务器并实现中继和Linux 下搭建DNS服务器(2个实验可跟做)
  4. Python机器学习:PCA与梯度上升002使用梯度上升法求解PCA问题
  5. 关于 HTTP 请求头的内容
  6. retrofitWrap
  7. angularjs 资源集合
  8. 获取到的数组在webview中成了字符串
  9. 基于图书管理系统的需求分析之数据流图
  10. java对excel插入水印_Java通过POI和JXL给Excel动态添加水印
  11. javascript中this和super用法
  12. 节点精灵 控制循环时间
  13. 米勒-拉宾素数检测法(判断一个极大的数是否为质数)——算法解析
  14. python pip 换源_Python pip换源教程
  15. Python中*args、**kws 理解与使用(可变参数以及关键字参数)
  16. 基于TencentOS-tiny实现PM2.5传感器(攀藤PMSA003)数据解析思路及实现
  17. C语言小作业字符串英文排序数组排序删除
  18. 当前服务器系统内核版本是多少,linux下如何查看系统和内核版本
  19. 我学ERP 之 金蝶ERP-K3_第4章 销售管理
  20. 铁路行业通信平台方案

热门文章

  1. typeof 操作符
  2. FindBugs规则整理
  3. NOI 3343 NOI3344热血和冷血格斗场
  4. 【转】网页调试语法错误代码说明(通用于IIS,MYSQL,FTP,ASP,VBScript)
  5. 微软提供5G的网络硬盘
  6. 【Java】iText POI
  7. 深度学习这么调参训练_深度学习调参及训练技巧(转)
  8. UI⑥Control族控件TextBox
  9. mysql学校信息管理系统_Mysql 学校信息管理系统
  10. 一文掌握jieba分词器的常见用法,附带案例