【安全算法之DES】DES算法(支持ECB/CBC模式)的C语言源码实现
概述 头文件定义 C语言版本的实现源码 数据分组模式:ECB模式和CBC模式 测试用例 github仓库 更多参考链接概述
大家都知道在安全领域,算法可谓是十分重要,而面对加密要求不算太高的场景,我们都可能会考虑使用对称算法,而不是采用非对称算法,主要是因为对称算法相对简单,计算复杂度较低。而作为比较前出现的对称算法,DES算法在对称算法领域一直占有很有重要的地位。
关于对称算法和非对称算法的区别,可以参考我之前的文章: 【安全算法之概述】一文带你简要了解常见常用的安全算法
今天给大家带来DES算法的C源码版本实现,本源码支持ECB模式和CBC模式,欢迎大家深入学习和讨论。头文件定义
头文件定义如下,主要定义了DES运算的数据块长度大小,以及3种可能的密钥长度,还有导出的2个API,一个用于数据加密,一个用于数据解密:
复制#ifndef __DES_H__ #define __DES_H__ #ifdef __cplusplus extern “C” { #endif /* __cplusplus */ #include #define DES_BLOCK_LEN 8 // 8bytes #define DES_KEY_LEN_8 8 // key-length: 8bytes -> single DES #define DES_KEY_LEN_16 16 // key-length: 16bytes -> triple DES (key1=key[0], key2=key[8], key3=key[0]) #define DES_KEY_LEN_24 24 // key-length: 24bytes -> triple DES (key1=key[0], key2=key[8], key3=key[16]) typedef enum _des_mode_e { DES_MODE_ECB, DES_MODE_CBC } des_mode_e; int32_t crypto_des_encrypt(const uint8_t *data, uint32_t data_len, uint8_t *out, const uint8_t *iv, const uint8_t *key, uint32_t key_len, des_mode_e mode); int32_t crypto_des_decrypt(const uint8_t *data, uint32_t data_len, uint8_t *out, const uint8_t *iv, const uint8_t *key, uint32_t key_len, des_mode_e mode); #ifdef __cplusplus } #endif /* __cplusplus */ #endif /*__DES_H__*/C语言版本的实现源码
下面是DES的C语言版本实现,主要也是围绕导出的2个数据加解密API,其中数据的分组模式,支持ECB模式和CBC模式:
复制 #include #include #include “des.h” #define DES_TRUE 0x01 #define DES_FALSE 0x00 #define DES_DO_INITIAL_PERMUTATION 0x10 #define DES_ENCRYPTION_MODE 0x20 #define DES_DECRYPTION_MODE 0 #define DES_DO_FINAL_PERMUTATION 0x40 #define DES_ENCRYPT_BLOCK (DES_DO_INITIAL_PERMUTATION|DES_ENCRYPTION_MODE|DES_DO_FINAL_PERMUTATION) #define DES_DECRYPT_BLOCK (DES_DO_INITIAL_PERMUTATION|DES_DECRYPTION_MODE|DES_DO_FINAL_PERMUTATION) const uint8_t IPP[64] = { 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 }; const uint8_t IPN[64] = { 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 }; //Inverse permutation const uint8_t Choose56[56] = { 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 }; //Choosing the 56bit key from 64bit const uint8_t key_round[32] = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1, 0, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 }; //shift key left //shift key right const uint8_t Choose48[48] = { 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 }; //expands the right half text of 32 bits to 48 bits const uint8_t E[48] = { 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 }; //Compression and permutation for key const uint8_t PP[32] = { 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 }; //P-box permutation const uint8_t S[8][64] = {{ 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 }, { 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 }, { 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 }, { 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 }, { 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 }, { 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 }, { 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 }, { 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 } }; const uint8_t _bitposition[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; static void check_table(uint8_t line, uint8_t *text, uint8_t *lasttext, const uint8_t *IDD) { uint8_t i, j, k, temp, temp2; for (j = 0, k = 0; j < line; j++, k += 8) { lasttext[j] = 0; for (i = 0; i < 8; i++) { temp2 = IDD[k + i]; temp = text[temp2 / 8]; // get the byte temp &= _bitposition[temp2 & 0x7]; // get the bit if (temp) { lasttext[j] |= _bitposition[i]; } } } } static void single_des_operation(uint8_t *plaintext, uint8_t *key, uint8_t mode) { static uint8_t prevtext[8]; uint8_t prevkey[8], Ltext[4], Rtext[4]; char temp, temp1; int32_t i = 0; int32_t Round = 0; uint8_t j = 0; if (mode & DES_DO_INITIAL_PERMUTATION) { check_table(8, plaintext, prevtext, IPP); //Initial permutation } for (i = 0; i < 4; i++) { Ltext[i] = prevtext[i]; Rtext[i] = prevtext[i + 4]; } check_table(7, key, prevkey, Choose56); for (Round = 0; Round < 16; Round++) { //rotate both 28bits block to left(encrypt) or right(decrypt) if (mode & DES_ENCRYPTION_MODE) { // encrypt for (j = 0; j < key_round[Round]; j++) { temp = prevkey[3] & 0x08; for (i = 7; i > 0; i–) { temp1 = prevkey[i – 1] & 0x80; prevkey[i – 1] <<= 1; if (temp) { prevkey[i – 1] |= 0x01; } temp = temp1; } if (temp) { prevkey[3] |= 0x10; } else { prevkey[3] &= 0xEF; } } } else { // decrypt for (j = 0; j < key_round[Round + 16]; j++) { temp = prevkey[3] & 0x10; for (i = 0; i < 7; i++) { temp1 = prevkey[i] & 0x01; prevkey[i] >>= 1; if (temp) { prevkey[i] |= 0x80; } temp = temp1; } if (temp) { prevkey[3] |= 0x08; } else { prevkey[3] &= 0xF7; } } } check_table(6, prevkey, plaintext, E); //Compression permutation check_table(6, Rtext, prevtext, Choose48); //Expansion permutation //Expanded right half xor_operation with the subkey prevtext[0] ^= plaintext[0]; prevtext[1] ^= plaintext[1]; prevtext[2] ^= plaintext[2]; prevtext[3] ^= plaintext[3]; prevtext[4] ^= plaintext[4]; prevtext[5] ^= plaintext[5]; for (j = 6, i = 8; j > 0; j -= 3, i -= 4) { //S-Box Substitution plaintext[i – 1] = prevtext[j – 1]; plaintext[i – 2] = ((prevtext[j – 1] >> 6) & 0x03) | (prevtext[j – 2] << 2); plaintext[i – 3] = ((prevtext[j – 2] >> 4) & 0x0f) | (prevtext[j – 3] << 4); plaintext[i – 4] = prevtext[j – 3] >> 2; } for (i = 0; i < 8; i++) { //Get the S-Box location temp = plaintext[i] & 0x21; if (temp & 0x01) { temp = (temp & 0x20) | 0x10; } plaintext[i] = temp | ((plaintext[i] >> 1) & 0x0F); } //Get S-Box output plaintext[0] = S[0][plaintext[0]]; plaintext[1] = S[1][plaintext[1]]; plaintext[2] = S[2][plaintext[2]]; plaintext[3] = S[3][plaintext[3]]; plaintext[4] = S[4][plaintext[4]]; plaintext[5] = S[5][plaintext[5]]; plaintext[6] = S[6][plaintext[6]]; plaintext[7] = S[7][plaintext[7]]; //Combine 4-bit block to form 32-bit block plaintext[0] = (plaintext[0] << 4) | plaintext[1]; plaintext[1] = (plaintext[2] << 4) | plaintext[3]; plaintext[2] = (plaintext[4] << 4) | plaintext[5]; plaintext[3] = (plaintext[6] << 4) | plaintext[7]; check_table(4, plaintext, prevtext, PP); for (i = 0; i < 4; i++) { prevtext[i] ^= Ltext[i]; Ltext[i] = Rtext[i]; Rtext[i] = prevtext[i]; } } for (i = 0; i < 4; i++) { prevtext[i] = Rtext[i]; prevtext[i + 4] = Ltext[i]; } if (mode & DES_DO_FINAL_PERMUTATION) { check_table(8, prevtext, plaintext, IPN); //Final permutation } } static int32_t xor_operation(uint8_t *out, const uint8_t *data1, const uint8_t *data2, uint32_t dwLen) { int32_t ret = DES_TRUE; uint32_t i = 0; if ((dwLen != 0) && ((data1 == NULL) || (data2 == NULL) || (out == NULL))) { ret = DES_FALSE; } else { for (i = 0; i < dwLen; i++) { out[i] = data1[i] ^ data2[i]; } } return ret; } int32_t crypto_des_encrypt(const uint8_t *data, uint32_t data_len, uint8_t *out, const uint8_t *iv, const uint8_t *key, uint32_t key_len, des_mode_e mode) { uint32_t i = 0; if ((data_len % DES_BLOCK_LEN != 0) || \ ((key_len != DES_KEY_LEN_8) && \ (key_len != DES_KEY_LEN_16) && \ (key_len != DES_KEY_LEN_24))) { return -1; } for (i = 0; i < data_len / DES_BLOCK_LEN; i++) { if (mode == DES_MODE_CBC) { if (i > 0) { xor_operation(&out[i * DES_BLOCK_LEN], &data[i * DES_BLOCK_LEN], \ &out[(i – 1) * DES_BLOCK_LEN], DES_BLOCK_LEN); } else { xor_operation(&out[i], &data[i], iv, DES_BLOCK_LEN); } } else { memcpy(&out[i * DES_BLOCK_LEN], &data[i * DES_BLOCK_LEN], DES_BLOCK_LEN); } if (key_len == DES_KEY_LEN_8) { //Single DES single_des_operation(&out[i * DES_BLOCK_LEN], (uint8_t *)&key[0], DES_ENCRYPT_BLOCK); } else { //Trip DES uint8_t *key1 = (uint8_t *)&key[0]; uint8_t *key2 = (uint8_t *)&key[DES_KEY_LEN_8]; uint8_t *key3 = (uint8_t *)&key[0]; if (key_len == DES_KEY_LEN_24) { key3 = (uint8_t *)&key[DES_KEY_LEN_16]; } single_des_operation(&out[i * DES_BLOCK_LEN], key1, DES_ENCRYPT_BLOCK); single_des_operation(&out[i * DES_BLOCK_LEN], key2, DES_DECRYPT_BLOCK); single_des_operation(&out[i * DES_BLOCK_LEN], key3, DES_ENCRYPT_BLOCK); } } return 0; } int32_t crypto_des_decrypt(const uint8_t *data, uint32_t data_len, uint8_t *out, const uint8_t *iv, const uint8_t *key, uint32_t key_len, des_mode_e mode) { int32_t i = 0; if ((data_len % DES_BLOCK_LEN != 0) || \ ((key_len != DES_KEY_LEN_8) && \ (key_len != DES_KEY_LEN_16) && \ (key_len != DES_KEY_LEN_24))) { return -1; } for (i = data_len / DES_BLOCK_LEN – 1; i >= 0; i–) { memcpy(&out[i * DES_BLOCK_LEN], &data[i * DES_BLOCK_LEN], DES_BLOCK_LEN); if (key_len == DES_KEY_LEN_8) { //Single DES single_des_operation(&out[i * DES_BLOCK_LEN], (uint8_t *)&key[0], DES_DECRYPT_BLOCK); } else { //Trip DES uint8_t *key1 = (uint8_t *)&key[0]; uint8_t *key2 = (uint8_t *)&key[DES_KEY_LEN_8]; uint8_t *key3 = (uint8_t *)&key[0]; if (key_len == DES_KEY_LEN_24) { key3 = (uint8_t *)&key[DES_KEY_LEN_16]; } single_des_operation(&out[i * DES_BLOCK_LEN], key3, DES_DECRYPT_BLOCK); single_des_operation(&out[i * DES_BLOCK_LEN], key2, DES_ENCRYPT_BLOCK); single_des_operation(&out[i * DES_BLOCK_LEN], key1, DES_DECRYPT_BLOCK); } if (mode == DES_MODE_CBC) { if (i > 0) { xor_operation(&out[i * DES_BLOCK_LEN], &out[i * DES_BLOCK_LEN], \ &data[(i – 1) * DES_BLOCK_LEN], DES_BLOCK_LEN); } else { xor_operation(&out[i], &out[i], iv, DES_BLOCK_LEN); } } } return 0; }数据分组模式:ECB模式和CBC模式
找了2张相关的图,描述得比较清晰,有助于大家理解:
简单来说,ECB分组模式就把数据划分为等长的数据块,在DES运算里面,这个数据块是8字节,然后对每个数据块进行加密解密操作,最后将所有的结果再次按序拼接在一起;每个数据块之间互不影响。
而CBC分组模式,它引入一个初始向量IV,它的运算流程如下:
加密流程
将原文数据划分成N组等长的数据块,在DES运算里面,这个数据块是8字节; 将IV向量与第一组数据块明文进行异或运算,然后把异或的结果传入DES加密流程,得到第一组密文; 将第一组密文与第二组数据块明文进行异或运算,然后把异或的结果传入DES加密流程,得到第二组密文; 以此类推,直到完成所有数据块的加密操作; 把所有的密文按照原来的顺序拼接起来,得到输出的密文。解密流程
将密文数据划分成N组等长的数据块,在DES运算里面,这个数据块是8字节; 一般从尾部数据块开始解密,把最后一组密文数据块传入DES解密流程,得到明文数据块后与倒数第二组密文数据块做异或运算,得到最后一组数据的明文; 把倒数第二组密文数据块传入DES解密流程,得到明文数据块后与倒数第三组密文数据块做异或运算,得到倒数第二组数据的明文; 以此类推,直到完成所有数据块的解密操作; 当解密完第一组数据密文后,要与初始向量IV做异或才得到第一组数据明文; 把所有的明文按照原来的顺序拼接起来,得到输出的明文。CBC分组模式的一个特点就是,有IV向量的参与,不同的输入IV会有不同的输出结果,并且之间直接的数据块是会有关联的。
测试用例
针对DES导出的两个加解密接口,以及ECB和CBC数组分组模式,我编写了以下测试用例:
复制 #include #include #include “des.h” #include “convert.h” int log_hexdump(const char *title, const unsigned char *data, int len) { char str[160], octet[10]; int ofs, i, k, d; const unsigned char *buf = (const unsigned char *)data; const char dimm[] = “+——————————————————————————+”; printf(“%s (%d bytes):\r\n”, title, len); printf(“%s\r\n”, dimm); printf(“| Offset : 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 0123456789ABCDEF |\r\n”); printf(“%s\r\n”, dimm); for (ofs = 0; ofs < (int)len; ofs += 16) { d = snprintf( str, sizeof(str), “| %08X: “, ofs ); for (i = 0; i < 16; i++) { if ((i + ofs) < (int)len) { snprintf( octet, sizeof(octet), “%02X “, buf[ofs + i] ); } else { snprintf( octet, sizeof(octet), ” ” ); } d += snprintf( &str[d], sizeof(str) – d, “%s”, octet ); } d += snprintf( &str[d], sizeof(str) – d, ” ” ); k = d; for (i = 0; i < 16; i++) { if ((i + ofs) < (int)len) { str[k++] = (0x20 <= (buf[ofs + i]) && (buf[ofs + i]) <= 0x7E) ? buf[ofs + i] : .; } else { str[k++] = ; } } str[k] = \0; printf(“%s |\r\n”, str); } printf(“%s\r\n”, dimm); return 0; } typedef struct _des_test_data_t { const char *name; const char *data; const char *cipher_exp; const char *key; const char *iv; int mode; } des_test_data_t; static des_test_data_t g_des_test_data[] = { { “DES_8-ECB-ENC-DEC”, “486328584376857876876876DFED458693696994369982784325876837265867”, “5D9D966FB7BD4C63C2452ADD63C75283D58253705EA8C9D2E2E69E4774C38DFF”, “C1D0F8FB4958670D”, “”, DES_MODE_ECB, }, { “DES_16-ECB-ENC-DEC”, “486328584376857876876876DFED458693696994369982784325876837265867”, “537B058DE0469097B657AB3639057FDE3A8AFF5D872BD02352C9785CCE9EDCA6”, “C1D0F8FB4958670DBA40AB1F3752EF0D”, “”, DES_MODE_ECB, }, { “DES_24-ECB-ENC-DEC”, “486328584376857876876876DFED458693696994369982784325876837265867”, “D7444666014085E167F20E9E6B592622CF74FB7C1F8AB3E05290C5AD81EA3140”, “C1D0F8FB4958670DBA40AB1F3752EF0D453D784F3784E389”, “”, DES_MODE_ECB, }, { “DES_8-CBC-ENC-DEC”, “486328584376857876876876DFED458693696994369982784325876837265867”, “799BFA00F4C3B2125DA1BA9185AB9B6C72940A92D7ABBDA1436F4C2C898B4D55”, “C1D0F8FB4958670D”, “876876DFED458693”, DES_MODE_CBC, }, { “DES_16-CBC-ENC-DEC”, “486328584376857876876876DFED458693696994369982784325876837265867”, “DE88B9AB8380320870E18130C306A2C953BAF27B2210EF0456B2CF90F6E2C1D3”, “C1D0F8FB4958670DBA40AB1F3752EF0D”, “876876DFED458693”, DES_MODE_CBC, }, { “DES_24-CBC-ENC-DEC”, “486328584376857876876876DFED458693696994369982784325876837265867”, “3788F49F44CFF611D1B638B0D0E71A2DB55304B3066EA2A5A864C7AC8FC111E5”, “C1D0F8FB4958670DBA40AB1F3752EF0D453D784F3784E389”, “876876DFED458693”, DES_MODE_CBC, }, }; #define ARRAY_SIZE(n) (sizeof(n)/sizeof(n[0])) static int des_test(des_test_data_t *data) { uint8_t data_hex[128]; uint16_t data_len; uint8_t data_exp_hex[128]; uint16_t data_exp_len; uint8_t key[24]; uint16_t key_len; uint8_t iv[24]; uint16_t iv_len; uint8_t data_calc[128]; uint8_t data_calc2[128]; int32_t ret; utils_hex_string_2_bytes(data->data, data_hex, &data_len); utils_hex_string_2_bytes(data->cipher_exp, data_exp_hex, &data_exp_len); utils_hex_string_2_bytes(data->key, key, &key_len); utils_hex_string_2_bytes(data->iv, iv, &iv_len); ret = crypto_des_encrypt(data_hex, data_len, data_calc, iv, key, key_len, data->mode); printf(“DES encrypt ret: %d\n”, ret); log_hexdump(“data_hex”, data_hex, data_len); log_hexdump(“data_calc”, data_calc, data_len); log_hexdump(“iv”, iv, 8); log_hexdump(“key”, key, key_len); if (!memcmp(data_calc, data_exp_hex, data_len)) { printf(“DES encrypt [%s] OK !\n”, data->name); } else { log_hexdump(“data_exp_hex”, data_exp_hex, data_len); log_hexdump(“data_calc”, data_calc, data_len); printf(“DES encrypt [%s] FAIL !\n”, data->name); ret = -1; goto exit_entry; } ret = crypto_des_decrypt(data_calc, data_len, data_calc2, iv, key, key_len, data->mode); printf(“DES decrypt ret: %d\n”, ret); log_hexdump(“data_calc”, data_calc, data_len); log_hexdump(“data_calc2”, data_calc2, data_len); log_hexdump(“iv”, iv, 8); log_hexdump(“key”, key, key_len); if (!memcmp(data_calc2, data_hex, data_len)) { printf(“DES decrypt [%s] OK !\n”, data->name); } else { log_hexdump(“data_hex”, data_hex, data_len); log_hexdump(“data_calc2”, data_calc2, data_len); printf(“DES decrypt [%s] FAIL !\n”, data->name); ret = -1; goto exit_entry; } exit_entry: return ret; } int main(int argc, const char *argv[]) { int ret; int i; int cnt = ARRAY_SIZE(g_des_test_data); for (i = 0; i < cnt; i++) { ret = des_test(&g_des_test_data[i]); if (ret < 0) { break; } } return 0; }测试用例比较简单,分为6组测试场景,分别是:
“DES_8-ECB-ENC-DEC”,“DES_16-ECB-ENC-DEC”,“DES_24-ECB-ENC-DEC”,“DES_8-CBC-ENC-DEC”,“DES_16-CBC-ENC-DEC”,“DES_24-CBC-ENC-DEC”,数据的原文都是486328584376857876876876DFED458693696994369982784325876837265867
但是使用不同的密钥长度和不同的分组模式,得出的密文是不一样的。
测试代码中,提前预置好了期望的密文值,当计算结果与期望值一致时,表示计算成功,反之就计算失败。同时,也欢迎大家设计提供更多的测试案例代码。
github仓库
以上代码和测试用例,及编译运行等,可以参考我的github仓库,有详细的流程介绍,欢迎大家交流讨论。如果有帮助到你的话,记得帮忙点亮一颗星哦。
更多参考链接
[1] 【安全算法的github仓库】
[2] 【安全算法之概述】一文带你简要了解常见常用的安全算法
免责声明:文章内容来自互联网,本站不对其真实性负责,也不承担任何法律责任,如有侵权等情况,请与本站联系删除。
转载请注明出处:【安全算法之DES】DES算法的C语言源码实现-des算法实例详解 https://www.yhzz.com.cn/a/7534.html