DES加密:8051实现(C语言) & FPGA实现(VHDL+NIOS II)

本文将利用C语言和VHDL语言分别实现DES加密,并在8051和FPGA上测试。

终于有机会阅读《深入浅出密码学一书》,趁此机会深入研究了DES加密的思想与实现。本文将分为两部分,第一部分为简单的C语言实现,第二部分为FPGA实现并在NIOS II核上测试该模块。

DES加密的思想

DES加密的由来网络上资料非常了,这里给出wikipedia链接: 维基百科

DES加密主要利用了两个工具

  • 利用替换来实现混淆,如DES加密中的S_box ,即将明文和密文之间存在的关系尽可能模糊。

  • 利用位置换来实现扩散,如DES加密中的IP 。实现扩散之后,可以隐藏明文的统计属性,即一个明文符号的改变会涉及到多个密文符号的加密操作。

DES利用的流程为 Feistel网络 该网络主要特点为加密过程和解密过程几乎完全相同。

DES加密的C语言实现

利用C语言实现DES加密分为几个步骤:

  • 第一步先将上文中所描述的 替换位置换 先实现。

  • 第二步实现 f函数 以及 子密钥生成

  • 最后实现完整的 DES加密 操作

下面分步骤实现这些部分

替换实现

替换利用C语言来实现并不复杂,可以直接用数组实现,例如 S-box 实现可以如下

for (i = 0; i < 8; i++){
    e_string[i] = (e_string[i] ^ round_key[i]) & 0x3F;
    e_string[i] = s[i] [e_string[i]];
}

位置换实现

位置换相对就复杂,抽象出一个函数,传入置换表和置换位数。根据置换表中描述的位数查看对应位是否为1。若为1,则在输出表中将对应位置为1。

/** transpose
 *  This function is going to use table to transpose trans_in_data into trans_out_data,
 *  while n is the number of bit which trans_out_data have.
 *  @Author Liu Nian, 2017
 */
void transpose(unsigned char *trans_in_data, unsigned char *trans_out_data,  
               unsigned char *table, unsigned char n){
    int i, bit_change;
    //clear trans_out_data
    for(i = 0; i < 8;i++)
        trans_out_data[i] = 0;
    //To transpose the bit_change bit 
    for(i = 0; i < n;i++){
        bit_change = *table++;
        //find the bit and check whether it is 1
        if (trans_in_data[bit_change>>3] & (0x80>>(bit_change & 7)))
            trans_out_data[i>>3] |= (0x80>>(i & 7));
    }
}

f函数实现

利用上述两个方法可以实现f函数,f函数实现如下:

/** f
 *  This function is going to mix round_key with 32-bit string.
 *  @Author Liu Nian, 2017
 */
void f(unsigned char *round_key, unsigned char *in_string, unsigned char *xor_string){
    unsigned char e_string[8];
    int i;
    transpose(in_string, e_string, E_table, 64);
    //Use S box for confussion
    for (i = 0; i < 8; i++){
        e_string[i] = (e_string[i] ^ round_key[i]) & 0x3F;
        e_string[i] = s[i] [e_string[i]];
    }
    transpose(e_string, xor_string, P_table, 32);
}

16轮子密钥生成

子密钥生成时,还用到了另一个工具,就是1,2,9,16轮加密时,左右32-bit密钥向左轮转1位,剩余情况则轮转2位。轮转用rotate_left 函数来实现。

/** rotate_left
 *  This function is going to make both left (32-bit) and right part of key rotate 1 bit.
 *  @Author Liu Nian, 2017
 */
void rotate_left(unsigned char *key){
    unsigned char str_x[8];
    unsigned char i;
    for (i=0; i < 8; ++i) 
        str_x[i] = key[i];
    for (i=0; i < 7; ++i){
        key[i] = (key[i] << 1);
        if ((i < 6) && ((str_x[i+1] & 128) == 128))
            key[i] |= 1;
    }
    if (str_x[0] & 0x80 )
        key[3] |= 0x10;
    else
        key[3] &= ~0x10;
    if (str_x[3] & 0x08 )
        key[6] |= 0x01;
    else
        key[6] &= ~0x01;
}

计算子密钥函数如下:

/** compute_subkeys
 *  This function is going to generate sub_keys.
 *  @Author Liu Nian, 2017
 */
void compute_subkeys(unsigned char *key){
    unsigned char i, j, in_key[8], out_key[8];
    // Store key in main_key
    for (i=0; i < 8; i++)
        main_key[i] = key[i];
    // Use PC_1_table to transpose 64-bit key into 56-bit in_key
    transpose(key, in_key, PC_1_table, 56);
    //Generate sub_keys for every round
    for (i=0; i < 16; i++){
        //For round 1,2,9,16 , key has to be rotate left 1 bit
        //For other rounds, key has to rotate left 2 bit
        for (j=0; j < round_turn[i]; j++) 
            rotate_left(in_key);
        // Use PC_2_table to transpose in_key to out_key
        transpose(in_key, out_key, PC_2_table,  64);
        for (j=0; j < 8; j++)
            sub_keys[i][j] = out_key[j];
    }
}

DES加密函数

将上述模块连接起来,完整整体DES加密。

/** DES function
 *  This function is used for DES encryption
 *  Input parameter
 *  unsigned char *plain_strng  :      pointer to 64 bits input string         
 *  unsigned char *key          :      pointer to 64 bits key string           
 *  unsigned char *ciph_strng   :      pointer to a 64 bits output string
 *  @Author Liu Nian, 2017
 */
void des(unsigned char *plain_strng, unsigned char *key, unsigned char *ciph_strng){
    unsigned char in_string[8], round_string[8], xor_string[8];
    unsigned char i, j, *round_key, temp;
    // compute subkeys which will be used in every round
    compute_subkeys(key);
    // Use transpose plain_strng into in_string
    transpose(plain_strng, in_string, IP_table, 64);
    // Encrypt for 16 round
    for (i = 0; i < 16; i++){
        // round_string is string which we will deal with in this round.
        for (j=0; j < 8; j++)
            round_string[j] = in_string[j];
        // round_key is the key which will be used in this round
        round_key = &sub_keys[i][0];
        // The first 32-bit of the next round string is the same as the last 32-bit of 
        // this round.
        for (j=0; j < 4; j++)
            in_string[j] = round_string[j+4];
        // Use f box to generate xor_string
        f(round_key, in_string, xor_string);
        // The last 32-bit of the next round string is the result of XOR between 
        // the fist 32-bit of this round and xor_string
        for (j=0; j < 4; j++) 
            in_string[j+4] = round_string[j] ^ xor_string[j];
    }
    // change the sequence of first 32-bit and last 32-bit
    for (j=0; j < 4; j++) {
        temp = in_string[j]; 
        in_string[j] = in_string[j+4]; 
        in_string[j+4] = temp;
    }
    // Use IP_1_table to transpose in_string into ciph_strng
    transpose(in_string, ciph_strng, IP_1_table, 64);
}

完整代码见附

DES加密的FPGA实现

DES加密的FPGA实现参考CoreTex Systems 公司的版本。

主要思想是利用状态机来在各个状态之间进行转移。详细代码可以参见CoreTex Systems

详细分析待后补充。

接入NIOS II核心并测试

由于NIOS II 核心只支持 32-bitPIO 的外设,故输入输出拆成2个32位 端口实现。

Qsys 编辑界面如下:

这里写图片描述

在顶层图上添加DES加密模块 如下:

这里写图片描述

测试代码如下:


#include <stdio.h>
#include "system.h"
#include "altera_avalon_pio_regs.h"

int main(){
    int i = 0x0A;
    unsigned int key_low = 0x12341234;
    unsigned int key_high = 0x12341234;
    unsigned int data_high = 0x01020304 ;
    unsigned int data_low = 0x05060708;
    unsigned int out_low;
    unsigned int out_high;
    int des_state = 0;
    printf("Des_test\n");
    IOWR_ALTERA_AVALON_PIO_DATA(PIO_LED_BASE,i);
    IOWR_ALTERA_AVALON_PIO_DATA(KEY_OUT_LOW_BASE,key_low);
    IOWR_ALTERA_AVALON_PIO_DATA(KEY_OUT_HIGH_BASE,key_high);
    IOWR_ALTERA_AVALON_PIO_DATA(DATA_OUT_HIGH_BASE,data_high);
    IOWR_ALTERA_AVALON_PIO_DATA(DATA_OUT_LOW_BASE,data_low);
    printf("Start des\n");
    //密钥明文传输完成,LD_DATA置1通知DES加密元件
    IOWR_ALTERA_AVALON_PIO_DATA(LD_DATA_BASE,1);

    //等待加密完成
    des_state = IORD_ALTERA_AVALON_PIO_DATA(DES_STATE_BASE);
    printf("des_state:%d\n",des_state);
    while(des_state & 0x1 == 0){
        printf("des_state:%d\n",des_state);
        usleep(10000);
        des_state = IORD_ALTERA_AVALON_PIO_DATA(DES_STATE_BASE);
    }
    //输出加密结果
    out_low = IORD_ALTERA_AVALON_PIO_DATA(DATA_IN_LOW_BASE);
    out_high = IORD_ALTERA_AVALON_PIO_DATA(DATA_IN_HIGH_BASE);
    printf("%x",out_high);
    printf("%x",out_low);
    return 0;
}

这里写图片描述

DES 加密C语言完整代码

#include <stdio.h>

/****************************************************************************************/
/*                                  Translation Table                                   */
/****************************************************************************************/
xdata const unsigned char IP_table[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
};

xdata const unsigned char IP_1_table[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
};

xdata const unsigned char swap[64] =
{
 33, 34, 35, 36, 37, 38, 39, 40,
 41, 42, 43, 44, 45, 46, 47, 48,
 49, 50, 51, 52, 53, 54, 55, 56,
 57, 58, 59, 60, 61, 62, 63, 64,
  1,  2,  3,  4,  5,  6,  7,  8,
  9, 10, 11, 12, 13, 14, 15, 16,
 17, 18, 19, 20, 21, 22, 23, 24,
 25, 26, 27, 28, 29, 30, 31, 32
};

xdata const unsigned char PC_1_table[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
};

xdata const unsigned char PC_2_table[64] =
{
    0,  0, 13,  4, 16, 10, 23,  0,
    0,  0,  2,  9, 27, 14,  5, 20,
    0,  0, 22,  7, 18, 11,  3, 25,
    0,  0, 15,  1,  6, 26, 19, 12,
    0,  0, 40, 54, 51, 30, 36, 46,
    0,  0, 29, 47, 39, 50, 44, 32,
    0,  0, 43, 52, 48, 38, 55, 33,
    0,  0, 45, 31, 41, 49, 35, 28
};

xdata const unsigned char E_table[64] =
{
    0,  0, 31,  4,  0,  1,  2,  3,
    0,  0,  3,  8,  4,  5,  6,  7,
    0,  0,  7, 12,  8,  9, 10, 11,
    0,  0, 11, 16, 12, 13, 14, 15,
    0,  0, 15, 20, 16, 17, 18, 19,
    0,  0, 19, 24, 20, 21, 22, 23,
    0,  0, 23, 28, 24, 25, 26, 27,
    0,  0, 27,  0, 28, 29, 30, 31
};

xdata const unsigned char P_table[32] =
{
    31, 14, 39, 44, 60, 23, 55, 36,
    4, 30, 46, 53, 12, 37, 62, 21,
    5, 15, 47, 29, 63, 54,  6, 20,
    38, 28, 61, 13, 45, 22,  7, 52
};

/****************************************************************************************/
/*                                 S Box                                                */
/****************************************************************************************/
xdata const unsigned char 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
    }
};

xdata const unsigned char round_turn[16] ={
    1,  1,  2,  2,  2,  2,  2,  2,  1,  2,  2,  2,  2,  2,  2,  1
};

unsigned char DES_Encrypt_key[8];
unsigned char DES_Decrypt_key[8];
unsigned char sub_keys[16][8];
unsigned char main_key[8];

void  des(unsigned char*, unsigned char*, unsigned char*);
static  void    transpose (unsigned char*, unsigned char*, const unsigned char*, unsigned char);
static  void    rotate_left (unsigned char*);
static  void    compute_subkeys (unsigned char*);
static  void    f (unsigned char*, unsigned char*, unsigned char*);


/** DES function
 *  This function is used for DES encryption
 *  Input parameter
 *  unsigned char *plain_strng  :      pointer to 64 bits input string         
 *  unsigned char *key          :      pointer to 64 bits key string           
 *  unsigned char *ciph_strng   :      pointer to a 64 bits output string
 *  @Author Liu Nian, 2017
 */
void des(unsigned char *plain_strng, unsigned char *key, unsigned char *ciph_strng){
    unsigned char in_string[8], round_string[8], xor_string[8];
    unsigned char i, j, *round_key, temp;
    // compute subkeys which will be used in every round
    compute_subkeys(key);
    // Use transpose plain_strng into in_string
    transpose(plain_strng, in_string, IP_table, 64);
    // Encrypt for 16 round
    for (i = 0; i < 16; i++){
        // round_string is string which we will deal with in this round.
        for (j=0; j < 8; j++)
            round_string[j] = in_string[j];
        // round_key is the key which will be used in this round
        round_key = &sub_keys[i][0];
        // The first 32-bit of the next round string is the same as the last 32-bit of 
        // this round.
        for (j=0; j < 4; j++)
            in_string[j] = round_string[j+4];
        // Use f box to generate xor_string
        f(round_key, in_string, xor_string);
        // The last 32-bit of the next round string is the result of XOR between 
        // the fist 32-bit of this round and xor_string
        for (j=0; j < 4; j++) 
            in_string[j+4] = round_string[j] ^ xor_string[j];
    }
    // change the sequence of first 32-bit and last 32-bit
    for (j=0; j < 4; j++) {
        temp = in_string[j]; 
        in_string[j] = in_string[j+4]; 
        in_string[j+4] = temp;
    }
    // Use IP_1_table to transpose in_string into ciph_strng
    transpose(in_string, ciph_strng, IP_1_table, 64);
}

/** transpose
 *  This function is going to use table to transpose trans_in_data into trans_out_data,
 *  while n is the number of bit which trans_out_data have.
 *  @Author Liu Nian, 2017
 */
void transpose(unsigned char *trans_in_data, unsigned char *trans_out_data,  
               unsigned char *table, unsigned char n){
    int i, bit_change;
    //clear trans_out_data
    for(i = 0; i < 8;i++)
        trans_out_data[i] = 0;
    //To transpose the bit_change bit 
    for(i = 0; i < n;i++){
        bit_change = *table++;
        //find the bit and check whether it is 1
        if (trans_in_data[bit_change>>3] & (0x80>>(bit_change & 7)))
            trans_out_data[i>>3] |= (0x80>>(i & 7));
    }
}


/** rotate_left
 *  This function is going to make both left (32-bit) and right part of key rotate 1 bit.
 *  @Author Liu Nian, 2017
 */
void rotate_left(unsigned char *key){
    unsigned char str_x[8];
    unsigned char i;
    for (i=0; i < 8; ++i) 
        str_x[i] = key[i];
    for (i=0; i < 7; ++i){
        key[i] = (key[i] << 1);
        if ((i < 6) && ((str_x[i+1] & 128) == 128))
            key[i] |= 1;
    }
    if (str_x[0] & 0x80 )
        key[3] |= 0x10;
    else
        key[3] &= ~0x10;
    if (str_x[3] & 0x08 )
        key[6] |= 0x01;
    else
        key[6] &= ~0x01;
}

/** compute_subkeys
 *  This function is going to generate sub_keys.
 *  @Author Liu Nian, 2017
 */
void compute_subkeys(unsigned char *key){
    unsigned char i, j, in_key[8], out_key[8];
    // Store key in main_key
    for (i=0; i < 8; i++)
        main_key[i] = key[i];
    // Use PC_1_table to transpose 64-bit key into 56-bit in_key
    transpose(key, in_key, PC_1_table, 56);
    //Generate sub_keys for every round
    for (i=0; i < 16; i++){
        //For round 1,2,9,16 , key has to be rotate left 1 bit
        //For other rounds, key has to rotate left 2 bit
        for (j=0; j < round_turn[i]; j++) 
            rotate_left(in_key);
        // Use PC_2_table to transpose in_key to out_key
        transpose(in_key, out_key, PC_2_table,  64);
        for (j=0; j < 8; j++)
            sub_keys[i][j] = out_key[j];
    }
}

/** f
 *  This function is going to mix round_key with 32-bit string.
 *  @Author Liu Nian, 2017
 */
void f(unsigned char *round_key, unsigned char *in_string, unsigned char *xor_string){
    unsigned char e_string[8];
    int i;
    transpose(in_string, e_string, E_table, 64);
    //Use S box for confussion
    for (i = 0; i < 8; i++){
        e_string[i] = (e_string[i] ^ round_key[i]) & 0x3F;
        e_string[i] = s[i] [e_string[i]];
    }
    transpose(e_string, xor_string, P_table, 32);
}

FPGA NIOSII 工程

CSDN下载频道

转载于:https://www.cnblogs.com/he11o-liu/p/7503240.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值