有限域的Lagrange插值分析ZUC流密码S盒的代数结构
有限域GF2^8的Lagrange插值分析ZUC流密码S盒的代数结构
- 背景
- ZUC流密码的结构
- ZUC流密码的S盒
- S盒(左)
- S盒(右)
- C++求解ZUC流密码的S盒的代数结构
- 有限域GF2^8的运算
- 多项式的运算
- 多项式的加法
- 多项式的乘法
- Lagrange差值
- 计算LagrangeLagrangeLagrange基函数的系数
- 计算LagrangeLagrangeLagrange基函数
- 计算LagrangeLagrangeLagrange差值多项式
- 插值结果
- S盒(左)的差值多项式Pol1Pol_1Pol1
- S盒(右)的差值多项式Pol2Pol_2Pol2
- 插值结果验证
- 验证S盒(左)的差值多项式Pol1Pol_1Pol1
- 验证S盒(右)的差值多项式Pol2Pol_2Pol2
背景
欧洲2000-2003年的NESSIE计划和2004-2008年的eSTREAM计划大大促进了流密码的发展,提出了很多新兴的流密码的设计思路和分析方法,很多新型的密码部件都在计划中提出了。提出了具有代表性的多个流密码,例如Grain,rivium,Mickey。我国密码专家在充分分析研究了前人的方案后,提出了国产的流密码方案——ZUC流密码。
ZUC流密码的结构
ZUC流密码的S盒
在密码学中,S盒(Substitution-box)是对称密钥算法执行置换计算的基本结构。S盒用在对称密码算法中,是唯一的非线性结构,其S盒的指标的好坏直接决定了密码算法的好坏。因此ZUC流密码结构中出现的两个S盒直接影响着ZUC流密码性能好坏。而然站在密码分析的角度,我们分析该密码部件的非线性度最佳方式就是对S盒的代数结构进行分析。所以我尝试采用C++语言来尝试用有限域GF28GF2^8GF28的Lagrange插值得到可以代表S盒代数结构的多项式。
S盒(左)
S盒(右)
C++求解ZUC流密码的S盒的代数结构
由于不是简单的计算某个Lagrange差值的数值结果,而是需要得到LagrangeLagrangeLagrange差值得到的多项式。因此我采用256256256维数组代表这个最高次数为255255255的多项式,数组存的便是这个多项式的系数。也就是程序运行的结果是一个256256256维数组。
有限域GF2^8的运算
多项式的加法和乘法运算过程中,系数在有限域GF28GF2^8GF28上进行运算,因此我首先写了进行有限域GF28GF2^8GF28加减乘除运算的类,代码核心是:采用查表的形式提高有限域运算的效率。有限域的素多项式选择为:
f(x)=x8+x4+x3+x+1f(x)=x^8+x^4+x^3+x+1f(x)=x8+x4+x3+x+1
有限域的生成元选择为:
g(x)=x+1g(x)=x+1g(x)=x+1
类的私有成员用来存储三张表:正表,反表,逆表。正表的下标代表有限域元素的阶,对应的数组内容即为该元素。反表的下标代表有限域元素本身,对应的数组内容为该元素对应的阶,逆表的每个下标对应的有限域元素与对应的数组内容存储的有限域元素互为逆元。
class Operator
{private:int P_Table[255];//正表:下标为阶数,元素为值,取值范围[0,255].int N_Table[256];//反表:下标为值,取值范围[0,255],元素为阶数.int R_Table[255];//逆元表:下标值与下标对应元素的值互为逆元。
public:Operator()//构造函数:用于得到运算所需的表{//用于构造正表P_Table[0] = 1;for(int i=1; i<255; ++i){P_Table[i] = (P_Table[i-1] << 1) ^ P_Table[i-1];//计算g^iif(P_Table[i] & 0x100)//判断上述过程得到的多项式次数是否达到8{P_Table[i] ^= 0x11b;//用技巧模m(x) = x^8 + x^4 + x^3 +x +1}}//用于构造反表for(int i=0; i<255; ++i){N_Table[ P_Table[i] ] = i;}//用于构造逆元表for(int i=1; i<256; ++i)//0没有逆元,所以从1开始{int k = N_Table[i];k = (255 - k) % 255;//m_table的取值范围为 [0, 254]R_Table[i] = P_Table[k];}}//有限域上的加法int GF_Add(const int &a, const int &b){return a^b;}//有限域上的乘法int GF_Mul(const int &x, const int &y){return(((x == 0) || (y == 0)) ? 0 : P_Table[(N_Table[x] + N_Table[y]) % 255] );}//有限域上的除法int GF_Div(const int &x, const int &y){return GF_Mul(x, R_Table[y]);}//观察正表,反表,逆表的内容void Show(){for(int i=0; i<255; ++i){cout << hex << P_Table[i] << " ";}cout << "\n" << endl;for(int i=1; i<256; ++i){cout << N_Table[i] << " ";}cout << "\n" << endl;for(int i=1; i<255; ++i){cout << hex << R_Table[i] << " ";}cout << "\n" << endl;}
};
}
多项式的运算
在整个LagrangeLagrangeLagrange差值过程中,多项式的运算只需要多项式的加法和多项式的乘法。因此本代码也只包含多项式的这两种运算。
多项式的加法
//多项式加法template <typename Type>Type* P_A(const Type *a, const int &Len1, const Type *b, const int &Len2){int Len3 = Max(Len1, Len2);//获得用于表示和多项式的数组的长度Type *arr = new Type[Len3];//为和多项式的数组开辟动态内存空间for(int i = 0; i<Len3; ++i)//将每个元素初始化为0{arr[i] = 0;}if (Len1 == Len3){for (int i=0; i<Len3; ++i)//将多项式最高次的次数高的数组赋给新的数组{arr[i] = a[i];}for (int i=Len2-1 ; i>=0; --i)//将多项式最高次的次数低的数组与新的数组相加{arr[Len1-(Len2-i)] = Operate_main.GF_Add(arr[Len1-(Len2-i)], b[i]);}}else{for (int i=0; i<Len3; ++i)//将多项式最高次的次数高的数组赋给新的数组{arr[i] = b[i];}for (int i=Len1-1; i>=0; --i)//将多项式最高次的次数低的数组与新的数组相加{arr[Len2-(Len1-i)] = Operate_main.GF_Add(arr[Len2-(Len1-i)], a[i]);}}return arr;}
多项式的乘法
//多项式乘法template <typename Type>Type* P_M(const Type *a, const int &Len1, const Type *b, const int &Len2){Type *arr = new Type[Len1 + Len2 - 1];//为积多项式的数组开辟动态内存空间for(int i = 0; i<Len1 + Len2 - 1; ++i)//将每个元素初始化为0{arr[i] = 0;}for (int i=Len2-1; i>=0; --i)//用数组b的元素分别去乘数组a{for (int j=Len1-1; j>=0 ; --j){arr[j+i] = Operate_main.GF_Add(arr[j+i], Operate_main.GF_Mul(b[i], a[j]));}}return arr;}
Lagrange差值
我将多项式Lagrange插值过程分为三步。
第一步,计算LagrangeLagrangeLagrange基函数的系数:
Coe=yi(xi+x1)(xi+x2)…(xi+x256)Coe=\frac{y_i}{(x_i+x_1)(x_i+x_2)\ldots(x_i+x_{256})} Coe=(xi+x1)(xi+x2)…(xi+x256)yi
第二步,计算LagrangeLagrangeLagrange基函数:
Bas=yi(x−x1)(x−x2)…(x−x256)(xi+x1)(xi+x2)…(xi+x256)Bas=\frac{y_i(x-x_1)(x-x_2)\ldots(x-x_{256})}{(x_i+x_1)(x_i+x_2)\ldots(x_i+x_{256})} Bas=(xi+x1)(xi+x2)…(xi+x256)yi(x−x1)(x−x2)…(x−x256)
第三步,计算LagrangeLagrangeLagrange差值多项式:
Pol=y1(x+x2)…(x+x256)(x1+x2)…(x1+x256)+y2(x+x1)…(x+x256)(x2+x1)…(x2+x256)+…+y256(x+x1)…(x+x255)(x256+x1)…(x256+x255)Pol=\frac{y_1(x+x_2)\ldots(x+x_{256})}{(x_1+x_2)\ldots(x_1+x_{256})}+\frac{y_2(x+x_1)\ldots(x+x_{256})}{(x_2+x_1)\ldots(x_2+x_{256})}+\ldots+\frac{y_{256}(x+x_1)\ldots(x+x_{255})}{(x_{256}+x_1)\ldots(x_{256}+x_{255})} Pol=(x1+x2)…(x1+x256)y1(x+x2)…(x+x256)+(x2+x1)…(x2+x256)y2(x+x1)…(x+x256)+…+(x256+x1)…(x256+x255)y256(x+x1)…(x+x255)
因此为此我以为写了三个函数分别来实现上述三步:
计算LagrangeLagrangeLagrange基函数的系数
//定义插值基函数的系数
int Lag_Bas_Coe(const int S[16][16], const int &Row, const int &Column)
{int X = Row * 0x10 + Column;//插值点的x值int Den = 1;//初始化分母for(int i=0; i<0x100; ++i)//迭代计算分母{if(i != X){Den = Operate_main.GF_Mul(Den, Operate_main.GF_Add(X, i));}}int Coe;//初始化系数return Coe = Operate_main.GF_Div(S[Row][Column], Den);
}
计算LagrangeLagrangeLagrange基函数
//定义拉格朗日插值的基函数
int* Lag_Bas_Fun(const int S[16][16], const int &Row, const int &Column)
{int X = Row * 0x10 + Column;//插值点的x值int tmp_1[2];//每一步迭代相乘的多项式int *tmp_main = new int[2];//主迭代多项式int count = 0;//用于迭代更新返回数组的长度for(int i=0; i<0x100; ++i){if(i != X){tmp_1[0] = 1;tmp_1[1] = i;int *tmp_2 = new int[2 + count];if(count == 0){for(int j=0; j<2; ++j){tmp_2[j] = tmp_1[j];}}else{tmp_2 = Polynomial_Operation::P_M<int>(tmp_main, 1 + count, tmp_1, 2);delete[] tmp_main;}tmp_main = new int[2 + count];//主迭代多项式for(int j=0; j<2+count; ++j){tmp_main[j] = tmp_2[j];}delete[] tmp_2;count++;}}int Coe = Lag_Bas_Coe(S, Row, Column);for(int i=0; i<0x100; ++i){tmp_main[i] = Operate_main.GF_Mul(tmp_main[i], Coe);}return tmp_main;
}
计算LagrangeLagrangeLagrange差值多项式
//定义差值多项式函数
int* Lag_Pol(const int S[16][16])
{int* tmp = new int[256];int* Pol = new int[256];for(int i=0; i<256; ++i){Pol[i] = 0;}for(int i=0; i<0x10; ++i){for(int j=0; j<0x10; ++j){tmp = Lag_Bas_Fun(S, i, j);Pol = Polynomial_Operation::P_A<int>(tmp, 256, Pol, 256);}}delete[] tmp;return Pol;
}
插值结果
现在我们来调用主函数查看差值多项式的结果:
int main()
{int *Pol = new int[256];//计算S盒的有限域拉格朗日插值多项式Pol = Lagrange::Lag_Pol();for(int i=0; i<256; ++i){cout << hex << Pol[i] <<" ";}cout << endl;delete[] Pol;return 0;
}
S盒(左)的差值多项式Pol1Pol_1Pol1
S盒(右)的差值多项式Pol2Pol_2Pol2
插值结果验证
为了验证这里得到多项式的正确性,我们需要计算有限域上全部256256256点对应的结果是否正确。为此我写了一个测试函数来测试结果的正确性:
//测试函数_用于验证多项式的正确性
int Test_Fun(const int *a, const int &len, const int &Row, const int &Column)
{int test_1;int test_2 = 0;int X = Row * 16 + Column;for(int i=0; i<256; ++i){test_1 = 1;for(int j=0; j<255-i; ++j){test_1 = Operate_main.GF_Mul(test_1,X);}test_2 = Operate_main.GF_Add(Operate_main.GF_Mul(test_1, a[i]), test_2);}return test_2;
}
并在主函数中调用该函数来进行测试:
int main()
{int* Pol = new int[256];Pol = Lagrange::Lag_Pol();for(int i=0; i<0x10; ++i){for(int j=0; j<0x10; ++j){cout << hex << Lagrange::Test_Fun(Pol, 256, i, j)<<" ";}cout << endl;}cout << endl;delete[] Pol;return 0;
}
验证S盒(左)的差值多项式Pol1Pol_1Pol1
验证S盒(右)的差值多项式Pol2Pol_2Pol2
经过验证,我发现得到的结果和ZUC流密码的两个S盒保持了一致。因此可以充分说明我成功的利用有限域GF28GF2^8GF28的LagrangeLagrangeLagrange插值得到了可以用来描述S盒非线性性质的多项式。
有限域的Lagrange插值分析ZUC流密码S盒的代数结构相关推荐
- 机器学习数据预处理之缺失值:插值法填充+ lagrange插值+拉格朗日插值
机器学习数据预处理之缺失值:插值法填充+ lagrange插值+拉格朗日插值 garbage in, garbage out. 没有高质量的数据,就没有高质量的数据挖掘结果,数据值缺失是数据分析中经常 ...
- Python实现Newton和lagrange插值
一.介绍 Newton和lagrange插值:给出一组数据进行Newton和lagrange插值,同时将结果用plot呈现出来 1.首先是Lagrange插值: 根据插值的方法,先对每次的结果求积,在 ...
- ARCGIS10.1 插值分析结果按指定多边形输出
ARCGIS中的插值分析功能不多赘述. 但插值分析的结果的大小范围是原始插值点的最小外接矩形.但实际中,往往需要以固定边界或指定多边形(比如某个行政区)输出结果. 在网上找到很多种方法,以下方法最便捷 ...
- ArcGIS实验教程——实验十三:栅格空间插值分析
ArcGIS实验视频教程合集:<ArcGIS实验教程从入门到精通>(附配套实验数据) >>> 实验前必读:<完美解决ArcGIS10.x栅格空间插值报错无法进行和导 ...
- 拉格朗日(lagrange)插值及其MATLAB程序
一.n次拉格朗日插值 根据<插值多项式的性质>中的定理6.1可得 其中(6.19)称为基函数,(6.18)称为拉格朗日多项式,用(6.18)计算插值称为拉格朗日多项式插值. 方法2:通过M ...
- c语言插值法编程,Lagrange插值的C语言编程.pdf
Lagrange插值的C语言编程 线性插值 给出两点(x , y ),i 0,1 ,则有线性插值函数 i i x −x x −x 1 0 L (x ) l (x )y =+l (x )y y =+ y ...
- 拉格朗日(lagrange)插值(MATLAB实现)
Author:HanDi 上海某高校遥感专业 工科男 相信积微者速成,相信分享的力量 CSDN@这可真是难为我了 在学习气溶胶光学厚度(AOD)反演算法时,遇到了插值方法选择上的难题.对于AOD反演一 ...
- 线性插值、抛物插值、Lagrange插值 | Lagrange拉格朗日插值法(一)
Lagrange(拉格朗日)插值法 Lagrange插值法是一种多项式插值方法. 1. 线性插值(两点插值或一次插值) 线性插值就是通过两个采样点 ( x 0 , y 0 ) (x_0,y_0) (x ...
- lagrange 插值实现和龙格现象
lagrange 插值实现 import numpy as np #数值运算 import sympy import matplotlib.pyplot as pltclass LagrangeInt ...
- 前端实现克里金插值分析(二)
作者:yangjunlin 在上一篇文章中我们已经使用了像素法实现克里金插值的方式,但是问题也就随之抛了出来.1.第一点,在反距离权重插值的时候,因为处理的数据量大会直接导致主线程卡,导致用户体验 ...
最新文章
- 国产scrum敏捷开发工具- leangoo领歌
- Java基础概念(一)
- java中object转int
- 《研磨设计模式》chap8 生成器模式Builder
- 在哪里编写写php,php扩展编写
- 创业型公司如何找有相同价值观的人(转)
- ORACLE 中的 ROW_NUMBER() OVER() 分析函数的用法
- matlab小波分析特征提取,基于小波分析的特征信号提取的matlab程序
- Excel表格快捷键技巧使用
- nginx反向代理打印日志_Nginx 反向代理 log 显示真IP地址
- 推荐免费下载430套大型企业管理源码 下载地址:http://www.hur.cn/tg/linkin.asp?linkid=205389 下载地址:[URL=http://www.hur.cn/t
- POJ 3693 Maximum repetition substring (后缀数组)
- 惊!Linux居然可以这样破解WiFi密码,竟然是?
- 监控广告变现效果,开发者该如何搭建数据分析体系,如何制定优化策略?
- Java岗大厂面试百日冲刺【Day50】— 秒杀系统2 (日积月累,每日三题)
- Python测试进阶(三)
- Android Studio Chipmunk 2021.2.1.15下载地址
- Paper reading (十八):Machine learning applications in genetics and genomics
- 【算法】_009_插入排序_二分查找优化
- Revit中复合墙图层的规则和CAD识别翻模墙