对FEAL-4的线性***
对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]
- /*
- * The FEAL cipher - Linear Cryptanalysis
- */
- #include <stdio.h>
- #include <stdlib.h>
- /* uncomment this next statement to activate linear cryptanalysis code... */
- #define DEBUG
- #define WORD32 unsigned int
- #define BYTE unsigned char
- //循环左移技巧
- #define ROT2(x) (((x)<<2) | ((x)>>6))
- #define S0(a,b) (ROT2((BYTE)((a)+(b))))
- #define S1(a,b) (ROT2((BYTE)((a)+(b)+1)))
- //字节数组化字技巧
- static WORD32 pack32(BYTE *b)
- { /* pack 4 bytes into a 32-bit Word */
- return ((WORD32)b[3]<<24)|((WORD32)b[2]<<16)|((WORD32)b[1]<<8)|(WORD32)b[0];
- }
- //字化字节数组技巧
- static void unpack32(WORD32 a,BYTE *b)
- { /* unpack bytes from a 32-bit word */
- b[0]=(BYTE)a;
- b[1]=(BYTE)(a>>8);
- b[2]=(BYTE)(a>>16);
- b[3]=(BYTE)(a>>24);
- }
- WORD32 f(WORD32 x,WORD32 key)
- {
- BYTE f[4];
- BYTE k[4];
- unpack32(x,f);
- unpack32(key,k);
- f[2]^=(f[3]^k[2]);
- f[1]^=(f[0]^k[1]);
- f[2]=S1(f[2],f[1]);
- f[1]=S0(f[1],f[2]);
- f[3]=S0(f[3]^k[3],f[2]);
- f[0]=S1(f[0]^k[0],f[1]);
- /* printf("%02x%02x%02x%02x\n",f[3],f[2],f[1],f[0]); */
- return pack32(f);
- }
- /* H for High, L for Low */
- void feal_encrypt(BYTE data[8],WORD32 *key)
- {
- int i;
- WORD32 H,L,T;
- H=pack32(&data[4]);
- L=H^pack32(&data[0]);
- T=L;
- L=H^f(L,key[0]);
- H=T;
- T=L;
- L=H^f(L,key[1]);
- H=T;
- L^=key[4];
- H^=key[5];
- T=L;
- L=H^f(L,key[2]);
- H=T;
- T=L;
- L=H^f(L,key[3]);
- H=T;
- H^=L;
- unpack32(L,&data[4]);
- unpack32(H,&data[0]);
- }
- void feal_decrypt(BYTE data[8],WORD32 *key)
- {
- int i;
- WORD32 H,L,T;
- L=pack32(&data[4]);
- H=L^pack32(&data[0]);
- T=H;
- H=L^f(H,key[3]);
- L=T;
- T=H;
- H=L^f(H,key[2]);
- L=T;
- L^=key[4];
- H^=key[5];
- T=H;
- H=L^f(H,key[1]);
- L=T;
- T=H;
- H=L^f(H,key[0]);
- L=T;
- L^=H;
- unpack32(H,&data[4]);
- unpack32(L,&data[0]);
- }
- int main(int argc,char **argv)
- {
- int i,j,lhs,rhs;
- int Ph10161826,Pl101826,Ch10161826,Cl16,Ch16;
- BYTE input[10];
- BYTE data[8],k[4];
- WORD32 key[6],ph,pl,ch,cl,k1;
- BYTE bits[4096];
- int first_time_in=1;
- /* DELETED - Secret key generator. Sets keys key[0] ... key[5] */
- key[1]=key[2]=key[3]=key[4]=key[5]=0; /* not the real key ! */
- key[0]=0x2E3500; /* !! This is the first sub-key we find! */
- #ifndef DEBUG
- argc--; argv++;
- if (argc!=8)
- {
- printf("command line error - input 8 bytes of plaintext in hex\n");
- printf("For example:-\n");
- printf("findkey 0 1 2 3 4e 5a f6 37\n");
- return 0;
- }
- for (i=0;i<8;i++)
- sscanf(argv[i],"%x",&input[i]);
- for (i=0;i<8;i++) data[i]=input[7-i];
- printf("Plaintext= ");
- for (i=7;i>=0;i--) printf("%02x ",data[i]);
- printf("\n");
- feal_encrypt(data,key);
- printf("Ciphertext= ");
- for (i=7;i>=0;i--) printf("%02x ",data[i]);
- printf("\n");
- feal_decrypt(data,key);
- printf("Plaintext= ");
- for (i=7;i>=0;i--) printf("%02x ",data[i]);
- printf("\n");
- #else
- for (i=0;i<8;i++) data[i]=(BYTE)rand();
- /*
- the debug code below searches through all k1[8~13] and k1[16~21],
- as described by Matsui. That's 4096 possibilities. It outputs a
- 0 or a 1 for each possible key.
- For all known plaintexts/ciphertexts the right key will always give the
- same fixed 0 or 1
- For each plaintext/ciphertext pair newly discovered wrong keys
- are replaced with an X
- */
- /* Now try for 60 random plaintexts... */
- for (j=0;j<60;j++)
- {
- for (i=0;i<8;i++) data[i]=(BYTE)rand(); /* random plaintexts */
- printf("\nPlaintext= ");
- for (i=7;i>=0;i--) printf("%02x ",data[i]);
- printf("\n");
- pl=pack32(&data[0]);
- ph=pack32(&data[4]);
- Ph10161826=((ph>>10)^(ph>>16)^(ph>>18)^(ph>>26))&1;
- Pl101826 =((pl>>10)^(pl>>18)^(pl>>26))&1;
- feal_encrypt(data,key);
- printf("Ciphertext= ");
- for (i=7;i>=0;i--) printf("%02x ",data[i]);
- printf("\n");
- cl=pack32(&data[0]);
- ch=pack32(&data[4]);
- Ch10161826=((ch>>10)^(ch>>16)^(ch>>18)^(ch>>26))&1;
- Cl16=((cl>>16)&1);
- Ch16=((ch>>16)&1);
- for (i=0;i<4096;i++)
- {
- //无关的位置0,用到的&出来
- k[0]=0; k[1]=i&0x3F; k[2]=(i>>6)&0x3F; k[3]=0;
- k1=pack32(k);
- lhs=(Ph10161826^Pl101826^Ch10161826^Cl16^(f(ph^pl,k1)>>16))&1;
- if (first_time_in) bits[i]=lhs;
- else if (lhs!=bits[i]) bits[i]=0xFF;
- }
- /* print out the 4096 bit array */
- for (i=0;i<4096;i++)
- {
- if (bits[i]==0xFF)
- {
- printf("X");
- continue;
- }
- printf("%d",bits[i]);
- }
- first_time_in=0;
- }
- printf("\nCandidates for bits 8-13, and 16-21 of key[0] are\n");
- for (i=0;i<4096;i++)
- {
- if (bits[i]==0xFF) continue;
- k[0]=0; k[1]=i&0x3F; k[2]=(i>>6)&0x3F; k[3]=0;
- k1=pack32(k);
- printf("%x\n",k1);
- }
- printf("Actual key[0] we were looking for = %x\n",key[0]);
- #endif
- return 0;
- }
转载于:https://blog.51cto.com/linuxcumt/709613
对FEAL-4的线性***相关推荐
- 数据结构(08)— 线性单链表基本操作
1. 线性单链表数据结构 // 假定每个结点的类型用 SNode 表示 typedef struct SNodeTag {int data; // 所存储的数据元素SNodeTag *next; // ...
- 数据结构(07)— 线性顺序表基本操作
1. 顺序表结构 #define MaxLen 50typedef struct {int data[MaxLen]; // 定义一个数组来存储线性表中所有元素int len; // 存储线性表的长度 ...
- 数据结构(05)— 线性单链表实战
1. 设计思路 本项目的实质是完成对考生信息的建立.查找.插入.修改.删除等功能,可以首先定义项目的数据结构,然后将每个功能写成一个函数来完成对数据的操作,最后完成主函数以验证各个函数功能并得出运行结 ...
- 数据结构(04)— 线性顺序表实战
1. 设计思路 本实战的实质是完成对学生成绩信息的建立.查找.插入.修改.删除等功能,可以首先定义项目的数据结构,然后将每个功能写成一个函数来完成对数据的操作,最后完成主函数以验证各个函数功能并得出运 ...
- leetcode 5. Longest Palindromic Substring 字符串中的最长回文数 逐步从O(n^2)优化至线性时间
题目 解析 思路一 暴力解法 思路二 指针+最大长度 思路3 由中间至两边找回数 思路4 Manacher's algorithm 线性时间 参考文档 题目 链接 给定一个字符串 s,找到 s 中最长 ...
- 数据结构与算法——线性结构——线性表及其表示
-"一,线性结构 1.顺序储存结构直接表示 多项式. 1).使用数组来表示多项式.(用数组下标来表示指数,值来表示系数) 可以表示成: 2).使用结构数组来表示.(把系数和指数看成一个二元组 ...
- 【Learning Notes】线性链条件随机场(CRF)原理及实现
1. 概述 条件随机场(Conditional Random Field, CRF)是概率图模型(Probabilistic Graphical Model)与区分性分类( Discriminativ ...
- NVIDIA GPU上的直接线性求解器
NVIDIA GPU上的直接线性求解器 NVIDIA cuSOLVER库提供了密集且稀疏的直接线性求解器和本征求解器的集合,它们为计算机视觉,CFD,计算化学和线性优化应用程序提供了显着的加速.cuS ...
- MegEngine亚线性显存优化
MegEngine亚线性显存优化 MegEngine经过工程扩展和优化,发展出一套行之有效的加强版亚线性显存优化技术,既可在计算存储资源受限的条件下,轻松训练更深的模型,又可使用更大batch siz ...
最新文章
- 小程序中textarea层级最高的结局办法
- Sharding-JDBC(三)3.1.0版本实践
- Linux ENSP 搭建DHCP服务器并实现中继和Linux 下搭建DNS服务器(2个实验可跟做)
- Python机器学习:PCA与梯度上升002使用梯度上升法求解PCA问题
- 关于 HTTP 请求头的内容
- retrofitWrap
- angularjs 资源集合
- 获取到的数组在webview中成了字符串
- 基于图书管理系统的需求分析之数据流图
- java对excel插入水印_Java通过POI和JXL给Excel动态添加水印
- javascript中this和super用法
- 节点精灵 控制循环时间
- 米勒-拉宾素数检测法(判断一个极大的数是否为质数)——算法解析
- python pip 换源_Python pip换源教程
- Python中*args、**kws 理解与使用(可变参数以及关键字参数)
- 基于TencentOS-tiny实现PM2.5传感器(攀藤PMSA003)数据解析思路及实现
- C语言小作业字符串英文排序数组排序删除
- 当前服务器系统内核版本是多少,linux下如何查看系统和内核版本
- 我学ERP 之 金蝶ERP-K3_第4章 销售管理
- 铁路行业通信平台方案