0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

【安全算法之DES】DES算法的C語(yǔ)言源碼實(shí)現(xiàn)

嵌入式物聯(lián)網(wǎng)開(kāi)發(fā) ? 來(lái)源:嵌入式物聯(lián)網(wǎng)開(kāi)發(fā) ? 作者:嵌入式物聯(lián)網(wǎng)開(kāi)發(fā) ? 2022-09-20 08:58 ? 次閱讀

【安全算法之DES】DES算法(支持ECB/CBC模式)的C語(yǔ)言源碼實(shí)現(xiàn)

  • 概述
  • 頭文件定義
  • C語(yǔ)言版本的實(shí)現(xiàn)源碼
  • 數(shù)據(jù)分組模式:ECB模式和CBC模式
  • 測(cè)試用例
  • github倉(cāng)庫(kù)
  • 更多參考鏈接


概述

大家都知道在安全領(lǐng)域,算法可謂是十分重要,而面對(duì)加密要求不算太高的場(chǎng)景,我們都可能會(huì)考慮使用對(duì)稱算法,而不是采用非對(duì)稱算法,主要是因?yàn)閷?duì)稱算法相對(duì)簡(jiǎn)單,計(jì)算復(fù)雜度較低。而作為比較前出現(xiàn)的對(duì)稱算法,DES算法在對(duì)稱算法領(lǐng)域一直占有很有重要的地位。
關(guān)于對(duì)稱算法和非對(duì)稱算法的區(qū)別,可以參考我之前的文章: 【安全算法之概述】一文帶你簡(jiǎn)要了解常見(jiàn)常用的安全算法
今天給大家?guī)?lái)DES算法的C源碼版本實(shí)現(xiàn),本源碼支持ECB模式和CBC模式,歡迎大家深入學(xué)習(xí)和討論。

頭文件定義

頭文件定義如下,主要定義了DES運(yùn)算的數(shù)據(jù)塊長(zhǎng)度大小,以及3種可能的密鑰長(zhǎng)度,還有導(dǎo)出的2個(gè)API,一個(gè)用于數(shù)據(jù)加密,一個(gè)用于數(shù)據(jù)解密:

#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語(yǔ)言版本的實(shí)現(xiàn)源碼

下面是DES的C語(yǔ)言版本實(shí)現(xiàn),主要也是圍繞導(dǎo)出的2個(gè)數(shù)據(jù)加解密API,其中數(shù)據(jù)的分組模式,支持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;
}

數(shù)據(jù)分組模式:ECB模式和CBC模式

找了2張相關(guān)的圖,描述得比較清晰,有助于大家理解:

在這里插入圖片描述


簡(jiǎn)單來(lái)說(shuō),ECB分組模式就把數(shù)據(jù)劃分為等長(zhǎng)的數(shù)據(jù)塊,在DES運(yùn)算里面,這個(gè)數(shù)據(jù)塊是8字節(jié),然后對(duì)每個(gè)數(shù)據(jù)塊進(jìn)行加密解密操作,最后將所有的結(jié)果再次按序拼接在一起;每個(gè)數(shù)據(jù)塊之間互不影響。

在這里插入圖片描述


而CBC分組模式,它引入一個(gè)初始向量IV,它的運(yùn)算流程如下:

加密流程

  • 將原文數(shù)據(jù)劃分成N組等長(zhǎng)的數(shù)據(jù)塊,在DES運(yùn)算里面,這個(gè)數(shù)據(jù)塊是8字節(jié);
  • 將IV向量與第一組數(shù)據(jù)塊明文進(jìn)行異或運(yùn)算,然后把異或的結(jié)果傳入DES加密流程,得到第一組密文;
  • 將第一組密文與第二組數(shù)據(jù)塊明文進(jìn)行異或運(yùn)算,然后把異或的結(jié)果傳入DES加密流程,得到第二組密文;
  • 以此類推,直到完成所有數(shù)據(jù)塊的加密操作;
  • 把所有的密文按照原來(lái)的順序拼接起來(lái),得到輸出的密文。

解密流程

  • 將密文數(shù)據(jù)劃分成N組等長(zhǎng)的數(shù)據(jù)塊,在DES運(yùn)算里面,這個(gè)數(shù)據(jù)塊是8字節(jié);
  • 一般從尾部數(shù)據(jù)塊開(kāi)始解密,把最后一組密文數(shù)據(jù)塊傳入DES解密流程,得到明文數(shù)據(jù)塊后與倒數(shù)第二組密文數(shù)據(jù)塊做異或運(yùn)算,得到最后一組數(shù)據(jù)的明文;
  • 把倒數(shù)第二組密文數(shù)據(jù)塊傳入DES解密流程,得到明文數(shù)據(jù)塊后與倒數(shù)第三組密文數(shù)據(jù)塊做異或運(yùn)算,得到倒數(shù)第二組數(shù)據(jù)的明文;
  • 以此類推,直到完成所有數(shù)據(jù)塊的解密操作;
  • 當(dāng)解密完第一組數(shù)據(jù)密文后,要與初始向量IV做異或才得到第一組數(shù)據(jù)明文;
  • 把所有的明文按照原來(lái)的順序拼接起來(lái),得到輸出的明文。

CBC分組模式的一個(gè)特點(diǎn)就是,有IV向量的參與,不同的輸入IV會(huì)有不同的輸出結(jié)果,并且之間直接的數(shù)據(jù)塊是會(huì)有關(guān)聯(lián)的。

測(cè)試用例

針對(duì)DES導(dǎo)出的兩個(gè)加解密接口,以及ECB和CBC數(shù)組分組模式,我編寫(xiě)了以下測(cè)試用例:


#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;
}

測(cè)試用例比較簡(jiǎn)單,分為6組測(cè)試場(chǎng)景,分別是:
“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”,

數(shù)據(jù)的原文都是486328584376857876876876DFED458693696994369982784325876837265867但是使用不同的密鑰長(zhǎng)度和不同的分組模式,得出的密文是不一樣的。
測(cè)試代碼中,提前預(yù)置好了期望的密文值,當(dāng)計(jì)算結(jié)果與期望值一致時(shí),表示計(jì)算成功,反之就計(jì)算失敗。

同時(shí),也歡迎大家設(shè)計(jì)提供更多的測(cè)試案例代碼。

github倉(cāng)庫(kù)

以上代碼和測(cè)試用例,及編譯運(yùn)行等,可以參考我的github倉(cāng)庫(kù),有詳細(xì)的流程介紹,歡迎大家交流討論。如果有幫助到你的話,記得幫忙點(diǎn)亮一顆星哦。

更多參考鏈接

[1] 【安全算法的github倉(cāng)庫(kù)】
[2] 【安全算法之概述】一文帶你簡(jiǎn)要了解常見(jiàn)常用的安全算法

審核編輯:湯梓紅
聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • C語(yǔ)言
    +關(guān)注

    關(guān)注

    180

    文章

    7575

    瀏覽量

    134027
  • DES
    DES
    +關(guān)注

    關(guān)注

    0

    文章

    64

    瀏覽量

    48145
  • 安全算法
    +關(guān)注

    關(guān)注

    0

    文章

    9

    瀏覽量

    6090
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    如何去實(shí)現(xiàn)DES加密算法?

    DES算法的簡(jiǎn)單原理是什么?如何去實(shí)現(xiàn)DES加密算法
    發(fā)表于 04-26 07:14

    什么是3-DES算法?如何去設(shè)計(jì)3-DES算法

    什么是3-DES算法?如何去設(shè)計(jì)3-DES算法
    發(fā)表于 04-28 07:10

    DES加密算法是什么

    一、加密算法1、 DES加密算法DES數(shù)據(jù)加密標(biāo)準(zhǔn),是一種使用密鑰加密的塊算法。DES中的密鑰k
    發(fā)表于 07-22 09:13

    3DES算法密鑰長(zhǎng)度說(shuō)明

    3DES算法密鑰長(zhǎng)度說(shuō)明3DES加密算法作為經(jīng)典的對(duì)稱加密算法,已經(jīng)廣泛應(yīng)用于各安全相關(guān)行業(yè)的數(shù)
    發(fā)表于 07-22 09:37

    用FPGA實(shí)現(xiàn)DES算法的密鑰簡(jiǎn)化算法

    介紹DES的密鑰算法,提出一種用預(yù)計(jì)算簡(jiǎn)化密鑰計(jì)算的方法并公布了預(yù)計(jì)算的C語(yǔ)言源程序。這種方法對(duì) DES的硬件
    發(fā)表于 04-07 09:41 ?14次下載

    des算法原理

    des算法原理 DES算法全稱為Data Encryption Standard,即數(shù)據(jù)加密算法,它是IBM公司于1975年研究成功并公開(kāi)
    發(fā)表于 01-16 10:07 ?2584次閱讀

    C語(yǔ)言實(shí)現(xiàn)DES算法

    C語(yǔ)言實(shí)現(xiàn)DES算法DES算法,使用了效率很高的C
    發(fā)表于 01-16 10:09 ?3242次閱讀

    利用匯編語(yǔ)言實(shí)現(xiàn)DES加密算法

    利用匯編語(yǔ)言實(shí)現(xiàn)DES加密算法 DES算法是一種數(shù)據(jù)加密算法。自從1977年公布以來(lái),一直是國(guó)
    發(fā)表于 04-07 09:24 ?1210次閱讀

    3DES算法的FPGA高速實(shí)現(xiàn)

    摘要:介紹3-DES算法的概要;以Xilinx公司SPARTANII結(jié)構(gòu)的XC2S100為例,闡述用FPGA高速實(shí)現(xiàn)3-DES算法的設(shè)計(jì)要點(diǎn)
    發(fā)表于 06-20 14:22 ?1425次閱讀
    3<b class='flag-5'>DES</b><b class='flag-5'>算法</b>的FPGA高速<b class='flag-5'>實(shí)現(xiàn)</b>

    基于51的DES算法演示

    DES算法演示,基于51的DES算法演示,程序?qū)W習(xí)??靵?lái)下載學(xué)習(xí)吧
    發(fā)表于 01-13 14:13 ?15次下載

    DES算法matlab代碼

    DES算法
    發(fā)表于 06-21 08:48 ?0次下載

    des加密解密算法詳解及源碼分享

    DES算法的入口參數(shù)有三個(gè):Key、Data、Mode。其中Key為7個(gè)字節(jié)共56位,是DES算法的工作密鑰;Data為8個(gè)字節(jié)64位,是要被加密或被解密的數(shù)據(jù);Mode為
    發(fā)表于 12-09 09:10 ?1.8w次閱讀
    <b class='flag-5'>des</b>加密解密<b class='flag-5'>算法</b>詳解及<b class='flag-5'>源碼</b>分享

    des算法與rsa算法有什么區(qū)別_比較

    DES算法為密碼體制中的對(duì)稱密碼體制,又被稱為美國(guó)數(shù)據(jù)加密標(biāo)準(zhǔn),是1972年美國(guó)IBM公司研制的對(duì)稱密碼體制加密算法DES算法具有極高
    發(fā)表于 12-09 09:27 ?1.9w次閱讀
    <b class='flag-5'>des</b><b class='flag-5'>算法</b>與rsa<b class='flag-5'>算法</b>有什么區(qū)別_比較

    c語(yǔ)言實(shí)現(xiàn)des加密算法詳細(xì)過(guò)程

     摘要:DES算法為密碼體制中的對(duì)稱密碼體制,又被稱為美國(guó)數(shù)據(jù)加密標(biāo)準(zhǔn),是1972年美國(guó)IBM公司研制的對(duì)稱密碼體制加密算法。明文按64位進(jìn)行分組,密鑰長(zhǎng)64位,密鑰事實(shí)上是56位參與DES
    發(fā)表于 12-10 11:28 ?3.5w次閱讀
    <b class='flag-5'>c</b><b class='flag-5'>語(yǔ)言實(shí)現(xiàn)</b><b class='flag-5'>des</b>加密<b class='flag-5'>算法</b>詳細(xì)過(guò)程

    DES算法的應(yīng)用誤區(qū)及安全性分析

    摘要:在銀行金融界及非金融界,越來(lái)越多地用到了DES 算法, DES 全稱為Data Encryption Standard即數(shù)據(jù)加密算法。下面來(lái)說(shuō)說(shuō)
    發(fā)表于 12-10 11:55 ?1.7w次閱讀