有限域GF2^8的Lagrange插值分析ZUC流密码S盒的代数结构
背景
欧洲2000-2003年的NESSIE计划和2004-2008年的eSTREAM计划大大促进了流密码的发展,提出了很多新兴的流密码的设计思路和分析方法,很多新型的密码部件都在计划中提出了。提出了具有代表性的多个流密码,例如Grain,rivium,Mickey。我国密码专家在充分分析研究了前人的方案后,提出了国产的流密码方案——ZUC流密码。
ZUC流密码的结构
ZUC流密码的S盒
在密码学中,S盒(Substitution-box)是对称密钥算法执行置换计算的基本结构。S盒用在对称密码算法中,是唯一的非线性结构,其S盒的指标的好坏直接决定了密码算法的好坏。因此ZUC流密码结构中出现的两个S盒直接影响着ZUC流密码性能好坏。而然站在密码分析的角度,我们分析该密码部件的非线性度最佳方式就是对S盒的代数结构进行分析。所以我尝试采用C++语言来尝试用有限域 G F 2 8 GF2^8 GF28的Lagrange插值得到可以代表S盒代数结构的多项式。
S盒(左)
S盒(右)
C++求解ZUC流密码的S盒的代数结构
由于不是简单的计算某个Lagrange差值的数值结果,而是需要得到 L a g r a n g e Lagrange Lagrange差值得到的多项式。因此我采用 256 256 256维数组代表这个最高次数为 255 255 255的多项式,数组存的便是这个多项式的系数。也就是程序运行的结果是一个 256 256 256维数组。
有限域GF2^8的运算
多项式的加法和乘法运算过程中,系数在有限域 G F 2 8 GF2^8 GF28上进行运算,因此我首先写了进行有限域 G F 2 8 GF2^8 GF28加减乘除运算的类,代码核心是:采用查表的形式提高有限域运算的效率。有限域的素多项式选择为:
f ( x ) = x 8 + x 4 + x 3 + x + 1 f(x)=x^8+x^4+x^3+x+1 f(x)=x8+x4+x3+x+1
有限域的生成元选择为:
g ( x ) = x + 1 g(x)=x+1 g(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^i
if(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;
}
};
}
多项式的运算
在整个 L a g r a n g e Lagrange Lagrange差值过程中,多项式的运算只需要多项式的加法和多项式的乘法。因此本代码也只包含多项式的这两种运算。
多项式的加法
//多项式加法
template <typename Type>
Type* P_A(const Type *a,