Pau*_* A. 5 encryption cryptography multiplication aes-gcm galois-field
我的GCM SP-800-38D文档中puting开块的乘法(Alogrithm 1)C代码这里.第11-12页.
完成代码后,我想看看是否有任何方法可以测试代码.您可以在我提供的代码下面找到附件.请注意,我使用24位块代替128位块,仅用于测试目的.如有必要,我将不胜感激.
void BLK_MUL (u8 *val_1,u8 *val_2, u8 *out_val)
{
u8 xdata R_val = 0xE1;
u8 xdata Z_val[3],V_val[3];
u8 mask_b = 0x80;
u16 i; u8 j;
bit rnd;
for(j=0;j<3;j++,++val_2)
{
Z_val[j]=0x00;
V_val[j]=*val_2;
}
for(i=0;i<24;i++)
{
if (*val_1 & mask_b)
{
for(j=0;j<3;j++)
Z_val[j]^=V_val[j];
}
if (!(V_val[2] & 0x01))
{//if LSB of V_val is 0
for(j=0;j<3;j++)
{ //V_val = rightshift(V_val)
if (j!=0)
if (V_val[2-j] & 0x01)
V_val[3-j] |= 0x80;
V_val[2-j]>>=1;
}
}
else
{//if LSB of V_val is 1
for(j=0;j<3;j++)
{//V_val = rightshift(V_val)
if (j!=0)
if (V_val[2-j] & 0x01)
V_val[3-j] |= 0x80;
V_val[2-j]>>=1;
}
V_val[0]^=R_val; //V_val = rightshift(V_val) ^ R
}
if(mask_b & 0x01) { val_1++; rnd=1;}
mask_b >>= 1;
if (rnd) { mask_b=0x80; rnd=0; }
}
STR_CPY(out_val,Z_val,3);
return ;
}
void main()
{
code unsigned char val_1[3] ={ 0x2b,0x7e,0x15 };
code unsigned char val_2[3] ={ 0x39,0x25,0x84 };
unsigned char out[3];
BLK_MUL (val_1,val_2,out);
return;
}
Run Code Online (Sandbox Code Playgroud)
在某些时候,您当然必须根据测试向量检查您的代码.但是,您可以执行相当多的测试而无需知道或计算任何测试向量.
首先,GF(2 ^ 128)中的乘法是可交换的.因此,您可以使用任何输入计算BLK_MUL(val_1,val_2,out1)和BLK_MUL(val_2,val_1,out2),您应该得到相同的结果.由于您的代码使用val_1和val_2不同,这已经是一个非常好的测试.
然后你可以使用那个乘法是分配的,即你可以测试(x + y)*z =(x*z)+(y*z),(其中GF(2 ^ 128)中的加法是由xoring对应计算的这两个值的字节在一起).
最后,一旦你实现了整个字段GF(2 ^ 128),你也可以利用它的顺序是2 ^ 128-1.即如果你从一个值x开始然后将它平方128次,那么你应该得到x.
一些额外的评论:
使用公式进行测试(仅使用测试向量)的优点是可以轻松运行大量测试.因为以这种方式添加测试相当容易,所以我经常首先使用稀疏输入(例如,在输入中设置单个位)进行一些简单的测试.如果出现问题,那么这有助于快速识别错误.
您当前的代码使用临时变量作为结果.这确实是一个好主意,因为它可以确保复制安全.我认为一个好的单元测试也应该涵盖这个案例.即你可能想要计算两次相同的结果:一次输入和输出指向不同的内存位置,一次输出与输入相同的内存.
此外,至少有一个其他答案谈到了优化.我认为如果你重构代码,那么你应该寻找有意义的组件来重用,而不是盲目地寻找类似代码片段.由于GF(2 ^ 128)是一个字段,因此字段中的加法和乘法当然是有意义的组件.另一个有意义的组件是多项式x的乘法(这是在加密中经常使用的东西).
| 归档时间: |
|
| 查看次数: |
2662 次 |
| 最近记录: |