如有错误和不足之处,敬请指正
#include <stdlib.h>
#include <memory.h>
#include <stdio.h>
//初始置换IP表
static const short IP[] = {
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,
56, 48, 40, 32, 24, 16, 8, 0,
58, 50, 42, 34, 26, 18, 10, 2,
60, 52, 44, 36, 28, 20, 12, 4,
62, 54, 46, 38, 30, 22, 14, 6
};
//逆初始置换IP-1表
static const short IP_M1[] = {
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,
32, 0, 40, 8, 48, 16, 56, 24
};
//拓展置换表E
static const short E[] = {
31, 0, 1, 2, 3, 4,
3, 4, 5, 6, 7, 8,
7, 8, 9, 10, 11, 12,
11, 12, 13, 14, 15, 16,
15, 16, 17, 18, 19, 20,
19, 20, 21, 22, 23, 24,
23, 24, 25, 26, 27, 28,
27, 28, 29, 30, 31, 0
};
//S盒
static const unsigned char Sn[][64] = {
/*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
},
/*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
},
/*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
},
/*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
},
/*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
},
/*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
},
/*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
},
/*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
}
};
//f函数内的置换P
static const short P[] = {
15, 6, 19, 20, 28, 11, 27, 16,
0, 14, 22, 25, 4, 17, 30, 9,
1, 7, 23, 13, 31, 26, 2, 8,
18, 12, 29, 5, 21, 10, 3, 24
};
//初始密钥置换PC-1
static const short PC_1[] = {
56, 48, 40, 32, 24, 16, 8, 0,
57, 49, 41, 33, 25, 17, 9, 1,
58, 50, 42, 34, 26, 18, 10, 2,
59, 51, 43, 35, 62, 54, 46, 38,
30, 22, 14, 6, 61, 53, 45, 37,
29, 21, 13, 5, 60, 52, 44, 36,
28, 20, 12, 4, 27, 19, 11, 3
};
//PC-2的轮密钥置换
static const short PC_2[] = {
13, 16, 10, 23, 0, 4, 2, 27,
14, 5, 20, 9, 22, 18, 11, 3,
25, 7, 15, 6, 26, 19, 12, 1,
40, 51, 30, 36, 46, 54, 29, 39,
50, 44, 32, 47, 43, 48, 38, 55,
33, 52, 45, 41, 49, 35, 28, 31
};
//加密时每轮密钥循环左位移的大小
static const short LSn[] = {
1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
};
//解密时每轮密钥循环右位移的大小
static const short RSn[] = {
0, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
};
//将src指向的bit位内存转换到dst中,每个bit位转换成一个byte,内容不变,input_length代表要转换的bit位总长度
static int bits2bytes(unsigned char* dst, unsigned char* src, unsigned int input_length) {
unsigned int i, j;
unsigned int tl = input_length >> 3;
unsigned int re = input_length & 0x07;
for (i = 0, j = 0; i < tl; ++i) {
dst[j++] = src[i] >> 7;
dst[j++] = src[i] >> 6 & 0x01;
dst[j++] = src[i] >> 5 & 0x01;
dst[j++] = src[i] >> 4 & 0x01;
dst[j++] = src[i] >> 3 & 0x01;
dst[j++] = src[i] >> 2 & 0x01;
dst[j++] = src[i] >> 1 & 0x01;
dst[j++] = src[i] & 0x01;
}
if (re) {
for (i = 0; i < re; ++i) {
dst[j++] = src[tl] >> (7 - i) & 0x01;
}
}
return 0;
}
//将src指向的byte内存转换到dst中,每8个byte位转换成一个byte,src指向的内存内容必须为0或1,input_length代表要转换的byte总长度
static int bytes2bits(unsigned char* dst, unsigned char* src, unsigned int input_length) {
unsigned int i, j, k;
unsigned int tl = input_length >> 3;
unsigned int re = input_length & 0x07;
unsigned char tbyte;
for (i = 0, j = 0; i < tl; ++i) {
tbyte = 0;
tbyte += src[j++] << 7;
tbyte += src[j++] << 6;
tbyte += src[j++] << 5;
tbyte += src[j++] << 4;
tbyte += src[j++] << 3;
tbyte += src[j++] << 2;
tbyte += src[j++] << 1;
tbyte += src[j++];
dst[i] = tbyte;
}
if (re) {
for (k = 0, tbyte = 0; k < re; ++k) {
tbyte += src[j++] << (7 - i);
}
dst[i] = tbyte;
}
return 0;
}
//des加密,data为明文——8bytes,key为密钥——8bytes,ciphertext为输出密文——8bytes
int des_encrypt(unsigned char* data, unsigned char* key, unsigned char* ciphertext) {
long int i, j, k, m;
unsigned char bdata[64];
unsigned char bkey[64];
unsigned char darr64[64];
unsigned char* Ln;
unsigned char* Rn;
unsigned char ERn[48];
unsigned char pRn[32];
unsigned char karr[56];
unsigned char Cn[56];
unsigned char Dn[56];
unsigned char* pfCn = (unsigned char*)(&Cn);
unsigned char* pfDn = (unsigned char*)(&Dn);
unsigned char tCnDn[56];
unsigned char kn[48];
unsigned char tS;
short int mapS;
if (data == NULL || key == NULL || ciphertext == NULL) {
goto fail;
}
//先将明文和密钥拆分每个bit位到数组中
bits2bytes(bdata, data, 64);
bits2bytes(bkey, key, 64);
//初始IP置换
for (i = 0; i < 64; ++i) {
darr64[i] = bdata[IP[i]];
}
//划分Ln和Rn
Ln = darr64;
Rn = darr64 + 32;
//密钥初始置换
for (i = 0; i < 56; ++i) {
karr[i] = bkey[PC_1[i]];
}
//将初始替换后的密钥分为左半部分和右半部分,分别复制两遍到另一个数组中,这样有利于移位
memcpy(Cn, karr, 28);
memcpy((unsigned char*)(&Cn) + 28, karr, 28);
memcpy(Dn, (unsigned char*)(&karr) + 28, 28);
memcpy((unsigned char*)(&Dn) + 28, (unsigned char*)(&karr) + 28, 28);
//16次轮加密
for (i = 0; i < 16; ++i) {
//调整指针位置,实际上实现的就是密钥编排中的移位
pfCn += LSn[i];
pfDn += LSn[i];
//调整完成后重新组一个数组
memcpy(tCnDn, pfCn, 28);
memcpy((unsigned char*)(&tCnDn) + 28, pfDn, 28);
for (j = 0; j < 48; ++j) {
//密钥编排中的PC-2置换
kn[j] = tCnDn[PC_2[j]];
//同时实现拓展置换E
ERn[j] = Rn[E[j]];
//轮密钥和拓展置换后结果进行异或
ERn[j] = ERn[j] ^ kn[j];
}
//8个S-盒
for (j = 0, k = 0, m = 0; j < 8; ++j, k += 6) {
//根据S-盒映射规则计算数组偏移量
mapS = ((ERn[k] << 1) + ERn[k + 5]) << 4;
mapS += (ERn[k + 1] << 3) + (ERn[k + 2] << 2) + (ERn[k + 3] << 1) + ERn[k + 4];
//找到S-盒对应数值
tS = Sn[j][mapS];
//数值转换为4个bit位
ERn[m++] = tS >> 3;
ERn[m++] = tS >> 2 & 0x01;
ERn[m++] = tS >> 1 & 0x01;
ERn[m++] = tS & 0x01;
}
for (j = 0; j < 32; ++j) {
//f函数内的P置换
pRn[j] = ERn[P[j]];
//结果和Ln异或
pRn[j] = pRn[j] ^ Ln[j];
}
//交换Ln和Rn
memcpy(darr64, Rn, 32);
memcpy((unsigned char*)(&darr64) + 32, pRn, 32);
}
//最后再次交换一次Ln和Rn
memcpy((unsigned char*)(&darr64) + 32, darr64, 32);
memcpy(darr64, pRn, 32);
//逆初始置换IP-1
for (i = 0; i < 64; ++i) {
bdata[i] = darr64[IP_M1[i]];
}
//数组合成byte
bytes2bits(ciphertext, bdata, 64);
return 0;
fail:
return -1;
}
//des解密,ciphertext为密文——8bytes,key为密钥——8bytes,data为输出明文——8bytes
int des_decrypt(unsigned char* ciphertext, unsigned char* key, unsigned char* data) {
long int i, j, k, m;
unsigned char bcipher[64];
unsigned char bkey[64];
unsigned char carr64[64];
unsigned char* Ln;
unsigned char* Rn;
unsigned char ERn[48];
unsigned char pRn[32];
unsigned char karr[56];
unsigned char Cn[56];
unsigned char Dn[56];
unsigned char* pfCn = (unsigned char*)(&Cn) + 28;
unsigned char* pfDn = (unsigned char*)(&Dn) + 28;
unsigned char tCnDn[56];
unsigned char kn[48];
unsigned char tS;
short int mapS;
if (ciphertext == NULL || key == NULL || data == NULL) {
goto fail;
}
//先将密文和密钥拆分每个bit位到数组中
bits2bytes(bcipher, ciphertext, 64);
bits2bytes(bkey, key, 64);
//初始IP置换
for (i = 0; i < 64; ++i) {
carr64[i] = bcipher[IP[i]];
}
//划分Ln和Rn
Ln = carr64;
Rn = carr64 + 32;
//密钥初始置换
for (i = 0; i < 56; ++i) {
karr[i] = bkey[PC_1[i]];
}
//将初始替换后的密钥分为左半部分和右半部分,分别复制两遍到另一个数组中,这样有利于移位
memcpy(Cn, karr, 28);
memcpy((unsigned char*)(&Cn) + 28, karr, 28);
memcpy(Dn, (unsigned char*)(&karr) + 28, 28);
memcpy((unsigned char*)(&Dn) + 28, (unsigned char*)(&karr) + 28, 28);
//16次轮解密
for (i = 0; i < 16; ++i) {
//调整指针位置,实际上实现的就是密钥编排中的移位
pfCn -= RSn[i];
pfDn -= RSn[i];
//调整完成后重新组一个数组
memcpy(tCnDn, pfCn, 28);
memcpy((unsigned char*)(&tCnDn) + 28, pfDn, 28);
for (j = 0; j < 48; ++j) {
//密钥编排中的PC-2置换
kn[j] = tCnDn[PC_2[j]];
//同时实现拓展置换E
ERn[j] = Rn[E[j]];
//轮密钥和拓展置换后结果进行异或
ERn[j] = ERn[j] ^ kn[j];
}
//8个S-盒
for (j = 0, k = 0, m = 0; j < 8; ++j, k += 6) {
//根据S-盒映射规则计算数组偏移量
mapS = ((ERn[k] << 1) + ERn[k + 5]) << 4;
mapS += (ERn[k + 1] << 3) + (ERn[k + 2] << 2) + (ERn[k + 3] << 1) + ERn[k + 4];
//找到S-盒对应数值
tS = Sn[j][mapS];
//数值转换为4个bit位
ERn[m++] = tS >> 3;
ERn[m++] = tS >> 2 & 0x01;
ERn[m++] = tS >> 1 & 0x01;
ERn[m++] = tS & 0x01;
}
for (j = 0; j < 32; ++j) {
//f函数内的P置换
pRn[j] = ERn[P[j]];
//结果和Ln异或
pRn[j] = pRn[j] ^ Ln[j];
}
//交换Ln和Rn
memcpy(carr64, Rn, 32);
memcpy((unsigned char*)(&carr64) + 32, pRn, 32);
}
//最后再次交换一次Ln和Rn
memcpy((unsigned char*)(&carr64) + 32, carr64, 32);
memcpy(carr64, pRn, 32);
//逆初始置换IP-1
for (i = 0; i < 64; ++i) {
bcipher[i] = carr64[IP_M1[i]];
}
//数组合成byte
bytes2bits(data, bcipher, 64);
return 0;
fail:
return -1;
}
int main() {
unsigned char data[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 };
unsigned char key[] = { 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 };
unsigned char cipher[8] = { 0 };
unsigned char plaintext[8] = { 0 };
int i;
des_encrypt(data, key, cipher);
for (i = 0; i < 8; ++i) {
printf("%#x ", cipher[i]);
}
printf("\n");
des_decrypt(cipher, key, plaintext);
for (i = 0; i < 8; ++i) {
printf("%#x ", plaintext[i]);
}
printf("\n");
return 0;
}
在MSVC2022环境下编译无问题。