本帖最后由 wangzhihai1986 于 2015-7-9 20:17 编辑
这段时间没有接外包项目了,又加之喜欢的电视剧每周更新太少,闲来无事,把以前学的加密算法分享下。:lol
这些代码都是参考网上资料,并对其进行了整理,所有代码都在STM32F407开发板上测试通过。
先贴出用到的常量表,如下。
static uint8_t Sbox[8][64]={ /* 选择函数表 */
{
14,4,13,1,2,15,11,8,3,10,6,12,5,9,0,7, /* S1 */
0,15,7,4,14,2,13,1,10,6,12,11,9,5,3,8,
4,1,14,8,13,6,2,11,15,12,9,7,3,10,5,0,
15,12,8,2,4,9,1,7,5,11,3,14,10,0,6,13
},
{
15,1,8,14,6,11,3,4,9,7,2,13,12,0,5,10, /* S2 */
3,13,4,7,15,2,8,14,12,0,1,10,6,9,11,5,
0,14,7,11,10,4,13,1,5,8,12,6,9,3,2,15,
13,8,10,1,3,15,4,2,11,6,7,12,0,5,14,9
},
{
10,0,9,14,6,3,15,5,1,13,12,7,11,4,2,8, /* S3 */
13,7,0,9,3,4,6,10,2,8,5,14,12,11,15,1,
13,6,4,9,8,15,3,0,11,1,2,12,5,10,14,7,
1,10,13,0,6,9,8,7,4,15,14,3,11,5,2,12
},
{
7,13,14,3,0,6,9,10,1,2,8,5,11,12,4,15, /* S4 */
13,8,11,5,6,15,0,3,4,7,2,12,1,10,14,9,
10,6,9,0,12,11,7,13,15,1,3,14,5,2,8,4,
3,15,0,6,10,1,13,8,9,4,5,11,12,7,2,14
},
{
2,12,4,1,7,10,11,6,8,5,3,15,13,0,14,9, /* S5 */
14,11,2,12,4,7,13,1,5,0,15,10,3,9,8,6,
4,2,1,11,10,13,7,8,15,9,12,5,6,3,0,14,
11,8,12,7,1,14,2,13,6,15,0,9,10,4,5,3,
},
{
12,1,10,15,9,2,6,8,0,13,3,4,14,7,5,11, /* S6 */
10,15,4,2,7,12,9,5,6,1,13,14,0,11,3,8,
9,14,15,5,2,8,12,3,7,0,4,10,1,13,11,6,
4,3,2,12,9,5,15,10,11,14,1,7,6,0,8,13
},
{
4,11,2,14,15,0,8,13,3,12,9,7,5,10,6,1, /* S7 */
13,0,11,7,4,9,1,10,14,3,5,12,2,15,8,6,
1,4,11,13,12,3,7,14,10,15,6,8,0,5,9,2,
6,11,13,8,1,4,10,7,9,5,0,15,14,2,3,12
},
{
13,2,8,4,6,15,11,1,10,9,3,14,5,0,12,7, /* S8 */
1,15,13,8,10,3,7,4,12,5,6,11,0,14,9,2,
7,11,4,1,9,12,14,2,0,6,10,13,15,3,5,8,
2,1,14,7,4,10,8,13,15,12,9,0,3,5,6,11
}
};
static uint8_t PC1[56]={ /* 转换选择1--用于密钥处理 */
57,49,41,33,25,17,9,
1,58,50,42,34,26,18,
10,2,59,51,43,35,27,
19,11,3,60,52,44,36,
63,55,47,39,31,23,15,
7,62,54,46,38,30,22,
14,6,61,53,45,37,29,
21,13,5,28,20,12,4
};
static uint8_t PC2[48]={ /* 转换选择2--用于密钥处理 */
14,17,11,24,1,5,
3,28,15,6,21,10,
23,19,12,4,26,8,
16,7,27,20,13,2,
41,52,31,37,47,55,
30,40,51,45,33,48,
44,49,39,56,34,53,
46,42,50,36,29,32
};
static uint8_t vIP[64]={ /* 初始转换表IP */
58,50,42,34,26,18,10,2,
60,52,44,36,28,20,12,4,
62,54,46,38,30,22,14,6,
64,56,48,40,32,24,16,8,
57,49,41,33,25,17,9,1,
59,51,43,35,27,19,11,3,
61,53,45,37,29,21,13,5,
63,55,47,39,31,23,15,7
};
static uint8_t invIP[64]={ /* 初始转换表的逆IP-1 */
40,8,48,16,56,24,64,32,
39,7,47,15,55,23,63,31,
38,6,46,14,54,22,62,30,
37,5,45,13,53,21,61,29,
36,4,44,12,52,20,60,28,
35,3,43,11,51,19,59,27,
34,2,42,10,50,18,58,26,
33,1,41,9,49,17,57,25
};
static uint8_t vE[48]={ /* 扩展表E */
32,1, 2, 3, 4, 5,
4, 5, 6, 7, 8, 9,
8, 9, 10,11,12,13,
12,13,14,15,16,17,
16,17,18,19,20,21,
20,21,22,23,24,25,
24,25,26,27,28,29,
28,29,30,31,32,1
};
static uint8_t vP[32]={ /* 转换函数表P */
16 ,7 ,20 , 21 ,
29,12 ,28 , 17 ,
1, 15 ,23 , 26 ,
5, 18 ,31 , 10 ,
2, 8 , 24 , 14 ,
32,27, 3 , 9 ,
19,13, 30 , 6 ,
22,11 ,4 , 25 };
以下为子函数实现。
/** 将1字节转换成8位
pIn@指向要转换成64个位的8个字节;
pOut@指向转换后返回的64个位。
**/
static void Byte2Bits(uint8_t *pIn, uint8_t *pOut)
{
int8_t i, j, tmp;
for(i=0; i<8; i++)
{
tmp = pIn;
for(j=i*8+7; j>=i*8; j--)
{
pOut[j] = tmp & 0x01; /* pOut[7]->LSB, pOut[0]->MSB */
tmp >>= 1;
}
}
}
/** 8位转换成1字节
pIn@指向要转换成8个字节的64个位;
pOut@指向转换后返回的8个字节。
**/
static void Bits2Byte(uint8_t *pIn, uint8_t *pOut)
{
uint8_t i, tmp;
for(i=0; i<8; i++)
{
tmp = i * 8;
pOut = (pIn[tmp]<<7) + (pIn[tmp+1]<<6) + (pIn[tmp+2]<<5) + (pIn[tmp+3]<<4)+
(pIn[tmp+4]<<3) + (pIn[tmp+5]<<2) + (pIn[tmp+6]<<1) + pIn[tmp+7]; /* pIn[0]->MSB, pIn[7]->LSB */
}
}
/** 异或操作
pIn1@指向参与异或操作的第一个变量;
pIn2@指向参与异或操作的第二个变量;
pOut@指向异或操作后的返回结果;
num@进行异或操作的个数。
**/
static void ByteXor(uint8_t *pIn1, uint8_t *pIn2, uint8_t *pOut, uint8_t num)
{
uint8_t i;
for(i=0; i<num; i++)
{
pOut = pIn1 ^ pIn2;
}
}
/** 将输入数据用已知表进行置换
pIn@指向要进行置换的数据;
pOut@指向置换后返回的数据;
pTable@指向定义好的置换表;
num@要置换的数据个数。
**/
static void Permutation(uint8_t *pIn, uint8_t *pOut, uint8_t *pTable, uint8_t num)
{
uint8_t i, tmp;
for(i=0; i<num; i++)
{
tmp = pTable - 1; /* 因为置换表是从1开始的,所以要减1 */
pOut = pIn[tmp];
}
}
/** 将64位数据转换成左右各32位数据
pIn@指向要分成左右两部分的数据;
pL@指向返回的左半部分数据;
pR@指向返回的右半部分数据;
num@要分半的数据个数,必须为偶数。
**/
static void DivideLR(uint8_t *pIn, uint8_t *pL, uint8_t *pR, uint8_t num)
{
uint8_t i, tmp;
tmp = num >> 1;
for(i=0; i<tmp; i++)
{
pL = pIn;
pR = pIn[i+tmp];
}
}
/** 置换Sbox
pIn@指向要进行选择表置换的数据;
pOut@指向置换后返回的数据。
**/
static void PermuSbox(uint8_t *pIn, uint8_t *pOut)
{
uint8_t i, j, tmp, t05, t14;
for(i=0; i<8; i++)
{
tmp = 6 * i;
t05 = (pIn[tmp] << 1) + pIn[tmp+5]; /* 取6位中的最高位和高低位组成新的2位,代表Sbox的行 */
t14 = (pIn[tmp+1] << 3) + (pIn[tmp+2] << 2) + (pIn[tmp+3] << 1) + pIn[tmp+4]; /* 6位的中间4位组成新的4位,代表Sbox的列 */
tmp = (t05 << 4) + t14; /* 4行16列--从0至63 */
tmp = Sbox[tmp]; /* 把6位输入按Sbox置换成4位输出(48->32) */
j = 4 * i;
pOut[j+0] = (tmp >> 3) & 0x01;
pOut[j+1] = (tmp >> 2) & 0x01;
pOut[j+2] = (tmp >> 1) & 0x01;
pOut[j+3] = tmp & 0x01; /* 转换成1位形式 */
}
}
/** 8字节块加密
pEncDat@指向要加密的数据,并返回它;
pKey@指向处理后的密钥。
**/
static void BlockEncrypt(uint8_t *pEncDat, uint8_t *pKey)
{
uint8_t i, j, EncTmp1[64], EncTmp2[64], pL[32], pR[32];
Byte2Bits(pEncDat, EncTmp1);
Permutation(EncTmp1, EncTmp2, vIP, 64); /* 按IP进行初始置换 */
DivideLR(EncTmp2, pL, pR, 64);
for(i=0; i<16; i++)
{
Permutation(pR, EncTmp1, vE, 48); /* 对右32位按E扩展到48位 */
ByteXor(EncTmp1, &pKey[i*48], EncTmp2, 48); /* 扩展后和第i轮密钥进行异或 */
PermuSbox(EncTmp2, EncTmp1); /* 按选择表进行置换 */
Permutation(EncTmp1, EncTmp2, vP, 32); /* 按P函数表把48位转换成32位 */
ByteXor(EncTmp2, pL, EncTmp1, 32); /* 和左32位进行异或 */
for(j=0; j<32; j++)
{
pL[j] = pR[j]; /* 上轮的右半部分作为下轮的左半部分 */
pR[j] = EncTmp1[j]; /* 处理后的32位作下轮的右半部分 */
}
}
for(j=0; j<32; j++) /* 合并成64位 */
{
EncTmp1[j] = pR[j];
EncTmp1[j+32] = pL[j];
}
Permutation(EncTmp1, EncTmp2, invIP, 64); /* 按IP的逆表进行置换 */
Bits2Byte(EncTmp2, pEncDat); /* 转换成8字节返回 */
}
/** 8字节块解密
pDecDat@指向要解密的数据,并返回它;
pKey@指向处理后密钥,同加密一样。
**/
static void BlockDecrypt(uint8_t *pDecDat, uint8_t *pKey)
{
uint8_t i, j, DecTmp1[64], DecTmp2[64], pL[32], pR[32];
Byte2Bits(pDecDat, DecTmp1);
Permutation(DecTmp1, DecTmp2, vIP, 64);
DivideLR(DecTmp2, pL, pR, 64);
for(i=16; i>0; i--)
{
Permutation(pR, DecTmp1, vE, 48);
ByteXor(DecTmp1, &pKey[(i-1)*48], DecTmp2, 48); /* 解密时密钥是从第16轮至第一轮进行的,同加密相反 */
PermuSbox(DecTmp2, DecTmp1);
Permutation(DecTmp1, DecTmp2, vP, 32);
ByteXor(DecTmp2, pL, DecTmp1, 32);
for(j=0; j<32; j++)
{
pL[j] = pR[j];
pR[j] = DecTmp1[j];
}
}
for(j=0; j<32; j++)
{
DecTmp1[j] = pR[j];
DecTmp1[j+32] = pL[j];
}
Permutation(DecTmp1, DecTmp2, invIP, 64);
Bits2Byte(DecTmp2, pDecDat);
}
加密流程:
1.输入8字节要加密数据,然后把8字节转换成位形式存储于64个字节中(注:高位存低字节,低位存高字节中,详情参看下面贴出的代码Byte2Bits函数);
2.按IP表对64位进行转换,得到新的64位。(参:Permutation函数)
3.把64位分成左右各32位。(参:DivideLR函数)
注:4至9步共循环16次(i<16)
4.按E表对R(右32位)扩展到48位。
5.把扩展后的R(48位)与key(密钥)进行异或操作。(参:ByteXor函数)
6.按Sbox(s1-s8)对第5步得到的48位进行转换,得到最终的32位。(参:PermuSbox函数)
7.把这个32位和P表置换。
8.然后再与L(左32位)进行异或。
9.组合LR为新的64位。
10.4-9步的16次循环后得到最终的64位,然后与IP-1表进行置换,完成一次加密。
11.把64位转为8字节,这就是加密后的8字节。 (参:Bits2Byte函数)
(解密时,4-9步倒着执行即可。)
|