[C] 纯文本查看 复制代码
#include <memory.h>
#include "DES.h"
int aPermutationChoice1Index[] = { 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 };
int aCyclicLeftShiftBits[] = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 };
int aPermutationChoice2Index[] = { 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 };
int aInitialPermutationIndex[] = { 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 };
int aDataExpansionTable[] = { 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 };
int S1[] = { 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
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 };
int S2[] = { 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
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 };
int S3[] = { 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
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 };
int S4[] = { 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
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 };
int S5[] = { 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
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 };
int S6[] = { 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
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 };
int S7[] = { 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
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 };
int S8[] = { 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
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 };
int aPermutationOperationIndex[] = { 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 };
int aFinalPermutationIndex[] = { 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 };
/*******************************************************************************
* 函数功能: 产生16个48位的子密钥
* 输入参数的说明:
1. pcDesKey是用户输入的8字节(64位)密钥的指针
2. pKeySets是指向17个KeySet结构数组的指针
* 注意:调用该函数之前,必须将pKeySets参数指向的结构数组初始化为0
*******************************************************************************/
void GenerateSubKeys(uint8_t* pcDesKey, PKeySet pKeySets)
{
int i, j;
int nShiftIndex;
uint8_t cShiftByte;
uint8_t cFirstShiftBit, cSecondShiftBit, cThirdShiftBit, cFourthShiftBit;
// 64位密钥首先执行置换选择PC-1,从中选出56位作为初始密钥,
// 存放于pKeySets[0].k的前7个字节中
for (i = 0; i < 56; i++)
{
nShiftIndex = aPermutationChoice1Index[i]; // 在原64位密钥中的索引
cShiftByte = 0x80 >> ((nShiftIndex - 1) % 8); // 这个索引在字节中的标志位
cShiftByte &= pcDesKey[(nShiftIndex - 1) / 8]; // 从8字节密钥中取对应的位
cShiftByte <<= ((nShiftIndex - 1) % 8); // 对应的位成为最高位
pKeySets[0].k[i / 8] |= (cShiftByte >> (i % 8));// 构成56位初始密钥,7个字节
}
// 把56位初始密钥分成两个28位的半密钥C0和D0,各使用3.5字节
for (i = 0; i < 3; i++)
{
pKeySets[0].c[i] = pKeySets[0].k[i];
}
pKeySets[0].c[3] = pKeySets[0].k[3] & 0xF0;
for (i = 0; i < 3; i++)
{
pKeySets[0].d[i] = (pKeySets[0].k[i + 3] & 0x0F) << 4;
pKeySets[0].d[i] |= (pKeySets[0].k[i + 4] & 0xF0) >> 4;
}
pKeySets[0].d[3] = (pKeySets[0].k[6] & 0x0F) << 4;
// 产生16个48位的子密钥
for (i = 1; i < 17; i++)
{
// C1 = C0, D1 = D0; C2 = C1, D2 = D1; …; C16 = C15, D16 = D15;
for (j = 0; j < 4; j++)
{
pKeySets[i].c[j] = pKeySets[i - 1].c[j];
pKeySets[i].d[j] = pKeySets[i - 1].d[j];
}
// 循环左移1或2位
nShiftIndex = aCyclicLeftShiftBits[i - 1];
if (nShiftIndex == 1)
cShiftByte = 0x80;
else
cShiftByte = 0xC0;
// 循环左移左半密钥C1,C2,…,C16
cFirstShiftBit = cShiftByte & pKeySets[i].c[0];
cSecondShiftBit = cShiftByte & pKeySets[i].c[1];
cThirdShiftBit = cShiftByte & pKeySets[i].c[2];
cFourthShiftBit = cShiftByte & pKeySets[i].c[3];
pKeySets[i].c[0] <<= nShiftIndex;
pKeySets[i].c[0] |= (cSecondShiftBit >> (8 - nShiftIndex));
pKeySets[i].c[1] <<= nShiftIndex;
pKeySets[i].c[1] |= (cThirdShiftBit >> (8 - nShiftIndex));
pKeySets[i].c[2] <<= nShiftIndex;
pKeySets[i].c[2] |= (cFourthShiftBit >> (8 - nShiftIndex));
pKeySets[i].c[3] <<= nShiftIndex;
pKeySets[i].c[3] |= (cFirstShiftBit >> (4 - nShiftIndex));
// 循环左移右半密钥D1,D2,…,D16
cFirstShiftBit = cShiftByte & pKeySets[i].d[0];
cSecondShiftBit = cShiftByte & pKeySets[i].d[1];
cThirdShiftBit = cShiftByte & pKeySets[i].d[2];
cFourthShiftBit = cShiftByte & pKeySets[i].d[3];
pKeySets[i].d[0] <<= nShiftIndex;
pKeySets[i].d[0] |= (cSecondShiftBit >> (8 - nShiftIndex));
pKeySets[i].d[1] <<= nShiftIndex;
pKeySets[i].d[1] |= (cThirdShiftBit >> (8 - nShiftIndex));
pKeySets[i].d[2] <<= nShiftIndex;
pKeySets[i].d[2] |= (cFourthShiftBit >> (8 - nShiftIndex));
pKeySets[i].d[3] <<= nShiftIndex;
pKeySets[i].d[3] |= (cFirstShiftBit >> (4 - nShiftIndex));
// 执行置换选择PC-2,从已经经过循环左移的56位密钥中选择出48位作为子密钥,
// 存放于pKeySets[i].k的前6个字节中
for (j = 0; j < 48; j++)
{
nShiftIndex = aPermutationChoice2Index[j]; // 在56位密钥中的索引
if (nShiftIndex <= 28)
{
cShiftByte = 0x80 >> ((nShiftIndex - 1) % 8); // 在字节中的标志位
cShiftByte &= pKeySets[i].c[(nShiftIndex - 1) / 8];// 取对应的位
cShiftByte <<= ((nShiftIndex - 1) % 8); // 对应的位成为最高位
}
else
{
cShiftByte = 0x80 >> ((nShiftIndex - 29) % 8);
cShiftByte &= pKeySets[i].d[(nShiftIndex - 29) / 8];
cShiftByte <<= ((nShiftIndex - 29) % 8);
}
pKeySets[i].k[j / 8] |= (cShiftByte >> (j % 8)); // 构成48位子密钥
}
}
}
/*******************************************************************************
* 函数功能: 对64位明文数据块进行DES加密;或对64位密文数据块进行DES解密
* 输入参数的说明:
1. pcMessageBlock是指向64位明文或密文数据块的指针
2. pcMessageResult指向的64位缓冲区用于返回明文或密文数据块的加密或解密结果
3. pKeySets是指向17个KeySet结构数组的指针
4. nMode参数用于指定执行模式,指定为自定义常量ENCRYPTION_MODE(1)表示加密,
指定为DECRYPTION_MODE(0)表示解密
* 注意:调用该函数之前,必须将pcMessageResult参数指向的缓冲区初始化为0
*******************************************************************************/
void ProcessMessage(uint8_t* pcMessageBlock, uint8_t* pcMessageResult,
PKeySet pKeySets, int nMode)
{
int i;
int nShiftIndex;
uint8_t cShiftByte;
uint8_t aInitialPermutation[8] = { 0 }; // 临时数组
uint8_t aL[4] = { 0 }, aR[4] = { 0 }; // L0和R0
// 初始置换IP,将64位明文数据打乱重新排列,存放于aInitialPermutation数组
for (i = 0; i < 64; i++)
{
nShiftIndex = aInitialPermutationIndex[i];
cShiftByte = 0x80 >> ((nShiftIndex - 1) % 8);
cShiftByte &= pcMessageBlock[(nShiftIndex - 1) / 8];
cShiftByte <<= ((nShiftIndex - 1) % 8);
aInitialPermutation[i / 8] |= (cShiftByte >> (i % 8));
}
// L0和R0
for (i = 0; i < 4; i++)
{
aL[i] = aInitialPermutation[i];
aR[i] = aInitialPermutation[i + 4];
}
// 左32位的Li,右32位的Ri,48位的中间结果,32位的S盒输出
uint8_t aLi[4] = { 0 }, aRi[4] = { 0 }, aMid[6] = { 0 }, aSOut[4] = { 0 };
int j, nKeyIndex;
// 开始16轮加密迭代,上边用于表示L0和R0的变量aL和aR,现在用于表示Li-1和Ri-1
for (i = 1; i <= 16; i++)
{
memcpy_s(aLi, 4, aR, 4); // Li = Ri-1
memset(aRi, 0, 4); // 右32位的Ri初始化为0
memset(aMid, 0, 6); // 48位的中间结果初始化为0
memset(aSOut, 0, 4); // 32位的S盒输出初始化为0
// 执行选择运算E,将右32位的Ri-1扩展为48位的中间结果,存放于aMid
for (j = 0; j < 48; j++)
{
nShiftIndex = aDataExpansionTable[j];
cShiftByte = 0x80 >> ((nShiftIndex - 1) % 8);
cShiftByte &= aR[(nShiftIndex - 1) / 8];
cShiftByte <<= ((nShiftIndex - 1) % 8);
aMid[j / 8] |= (cShiftByte >> (j % 8));
}
// 加密的话,依次使用子密钥索引1,2,…,16;解密则反之,使用16,15,…,1
if (nMode == ENCRYPTION_MODE)
nKeyIndex = i;
else
nKeyIndex = 17 - i;
// 通过选择运算E产生的48位数据再与子密钥Ki执行异或运算
for (j = 0; j < 6; j++)
aMid[j] ^= pKeySets[nKeyIndex].k[j];
// 执行8个代替函数(S盒)
uint8_t cRow, cColumn; // S盒代替矩阵的行索引、列索引
// 请结合下面的48位数据以辅助理解8个代替函数(S盒)的工作流程,r表示行,c表示列
// 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
// rccc crrc cccr rccc crrc cccr rccc crrc cccr rccc crrc cccr
// Byte 1(S1的输出 + S2的输出)
cRow = 0;
cRow |= ((aMid[0] & 0x80) >> 6); // 取第1位
cRow |= ((aMid[0] & 0x04) >> 2); // 取第6位
cColumn = 0;
cColumn |= ((aMid[0] & 0x78) >> 3); // 取中间4位
aSOut[0] |= ((uint8_t)S1[cRow * 16 + cColumn] << 4);
cRow = 0;
cRow |= (aMid[0] & 0x02); // 取第1位
cRow |= ((aMid[1] & 0x10) >> 4); // 取第6位
cColumn = 0;
cColumn |= ((aMid[0] & 0x01) << 3);
cColumn |= ((aMid[1] & 0xE0) >> 5); // 取中间4位
aSOut[0] |= (uint8_t)S2[cRow * 16 + cColumn];
// Byte 2(S3的输出 + S4的输出)
cRow = 0;
cRow |= ((aMid[1] & 0x08) >> 2);
cRow |= ((aMid[2] & 0x40) >> 6);
cColumn = 0;
cColumn |= ((aMid[1] & 0x07) << 1);
cColumn |= ((aMid[2] & 0x80) >> 7);
aSOut[1] |= ((uint8_t)S3[cRow * 16 + cColumn] << 4);
cRow = 0;
cRow |= ((aMid[2] & 0x20) >> 4);
cRow |= (aMid[2] & 0x01);
cColumn = 0;
cColumn |= ((aMid[2] & 0x1E) >> 1);
aSOut[1] |= (uint8_t)S4[cRow * 16 + cColumn];
// Byte 3(S5的输出 + S6的输出)
cRow = 0;
cRow |= ((aMid[3] & 0x80) >> 6);
cRow |= ((aMid[3] & 0x04) >> 2);
cColumn = 0;
cColumn |= ((aMid[3] & 0x78) >> 3);
aSOut[2] |= ((uint8_t)S5[cRow * 16 + cColumn] << 4);
cRow = 0;
cRow |= (aMid[3] & 0x02);
cRow |= ((aMid[4] & 0x10) >> 4);
cColumn = 0;
cColumn |= ((aMid[3] & 0x01) << 3);
cColumn |= ((aMid[4] & 0xE0) >> 5);
aSOut[2] |= (uint8_t)S6[cRow * 16 + cColumn];
// Byte 4(S7的输出 + S8的输出)
cRow = 0;
cRow |= ((aMid[4] & 0x08) >> 2);
cRow |= ((aMid[5] & 0x40) >> 6);
cColumn = 0;
cColumn |= ((aMid[4] & 0x07) << 1);
cColumn |= ((aMid[5] & 0x80) >> 7);
aSOut[3] |= ((uint8_t)S7[cRow * 16 + cColumn] << 4);
cRow = 0;
cRow |= ((aMid[5] & 0x20) >> 4);
cRow |= (aMid[5] & 0x01);
cColumn = 0;
cColumn |= ((aMid[5] & 0x1E) >> 1);
aSOut[3] |= (uint8_t)S8[cRow * 16 + cColumn];
// 8个S盒输出的32位数据再执行置换运算P,放入Ri
for (j = 0; j < 32; j++)
{
nShiftIndex = aPermutationOperationIndex[j];
cShiftByte = 0x80 >> ((nShiftIndex - 1) % 8);
cShiftByte &= aSOut[(nShiftIndex - 1) / 8];
cShiftByte <<= ((nShiftIndex - 1) % 8);
aRi[j / 8] |= (cShiftByte >> (j % 8));
}
// F(Ri-1, Ki)⊕Li-1
for (j = 0; j < 4; j++)
aRi[j] ^= aL[j];
// Li和Ri作为下一轮加密迭代的Li-1和Ri-1
for (j = 0; j < 4; j++)
{
aL[j] = aLi[j];
aR[j] = aRi[j];
}
}
// 16轮加密迭代已经结束,但是每一轮都有执行左右交换,现在,需要再左右交换回来
uint8_t aFinalPermutation[8];
for (j = 0; j < 4; j++)
{
aFinalPermutation[j] = aR[j];
aFinalPermutation[4 + j] = aL[j];
}
// 执行初始置换的逆FP
for (j = 0; j < 64; j++)
{
nShiftIndex = aFinalPermutationIndex[j];
cShiftByte = 0x80 >> ((nShiftIndex - 1) % 8);
cShiftByte &= aFinalPermutation[(nShiftIndex - 1) / 8];
cShiftByte <<= ((nShiftIndex - 1) % 8);
pcMessageResult[j / 8] |= (cShiftByte >> (j % 8));
}
}