简单讲述DES加密算法


鄙人最近刚刚接触DES加密算法, 虽然理解不深,但是在这里可以简单描述一下该算法。


一、算法简单介绍;

数据加密标准(Data Encryption Standard,DES)是美国标准技术研究院(National Institue of Standard and Technology, NIST)于1977年发布的一块对称密钥块密码。自从发布以来,DES使用得最广泛的对称密钥块密码。(以下摘自百度百科)数据加密算法(Data Encryption Algorithm,DEA)是一种对称加密算法,很可能是使用最广泛的密钥系统,特别是在保护金融数据的安全中,最初开发的DEA是嵌入硬件中的。通常,自动取款机(Automated Teller Machine,ATM)都使用DEA。它出自IBM的研究工作,IBM也曾对它拥有几年的专利权,但是在1983年已到期后,处于公有范围中,允许在特定条件下可以免除专利使用费而使用。1977年被美国政府正式采纳。


二、算法描述:

DES是对64位明文处理为64位密文,所以对于一个数据,我们可以把它分为一块块的64为数据块。而密钥是一个长度8字节64位的字符串,虽然有64位,但是密钥的第8、16、24、32、40、48、56、64位为校验位,所以实际上密钥只是56位。

DES算法过程:

1、首先,对这56位密钥进行如下表的换位:

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,

表的意思是第57位移到第1位,第49位移到第2位,...... 以此类推。变换后得到56bit数据,将它分成两部分,C[0][28], D[0][28]。(ps:C[0][28],D[0][28]中的“0”表示为初始密钥,我们同样用“1”表示密钥变换一次, 同理2, 3。。。);


2、计算16个子密钥(subkeys),计算方法C[i][28] D[i][28]为对前一个C[i-1][28], D[i-1][28]做循环左移操作。16次的左移位数如下表:

 1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16   (第i次)
 1,  1,  2,  2,  2,  2,  2,  2,  1,   2,  2,   2,   2,   2,   2,  1    (左移位数)

(循环左移:举个简单例子,4, 5, 2, 3, 1循环左移一位即是5, 2, 3, 1, 4; 循环左移两位即是2, 3, 1, 4, 5);


3、将上步计算出来的C[i][28] D[i][28] 得到56位,分别对它进行如下变换得到48位子密钥K[i][48]

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,

表的意思是第14位移到第1位,第17位移到第2位,以此类推。在此过程中,我们丢弃了9,18,22,25, 35,38,43,54位。

这样,我们现在已经得到了16个48位的子密钥,我们记为subkeys[16][48];

以上,三个步骤,我们对密钥的操作处理完毕。接着开始对明文处理。


4、我们把64为明文按下表初始换位值换:

58, 50, 12, 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

表的意思就是第一次变换时,第58位移到第1位,第50位移到第2位,...... 依此类推。得到64位数据,将这数据前后分成两块L[0][32], R[0][32]。(同理,此处L[0][32]、R[0][32]中的"0"表示初始明文,同样用“1”表示变换了一次之后的明文,同理2,3........);


5、我们把R[i][32]按下表扩展位48位,记坐Extern(R[i][32]) = R[i][48]

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


6、我们对R[i][48]与subkeys[i][48]异或运算,然后对这48位分为6位一组,记为B[8][6]


7、 使用S[i]替换B[i][6]。过程如下: 取出B[i][6]的第1位和第6位连成一个2位数m, m就是S[i]中对应的行数(0-3),取出B[i][6]的第2到第5位连成一个4位数n(0-15),n就是S[i]中对应的列数,用S[i][m][n]代替B[i][6]。S是4行16列的对应表,里面是4位的数,一共有8个S,定义如下:

S[1]:
   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,
S[2]:
   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,
S[3]:
   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,
S[4]:
    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,
S[5]:
 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,
S[6]:
 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,
S[7]:
 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,
S[8]:
 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,


8. 将从B[i][6]经过S得到的8个4位数连起来得到32位数。对这个数的32位进行如下变换:

   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,

  得到的结果赋给R[i][32], L[i][32]与R[i][32]作异或运算,把结果赋给L[i][32]。


9. 重新构造此时的“明文”:前32位为R[i][32],后32位为L[i][32];(8、9操作不理解可以参看后面的代码)


10. 按下表对此时的“明文”做变换。这是对第4步的一个逆变化。

 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


以上即是DES加密过程,解密只需把16个子密钥颠倒顺序。


三、DES加密算法不足:

 攻击 DES 的主要形式被称为蛮力的或彻底密钥搜索,即重复尝试各种密钥直到有一个符合为止。如果 DES 使用 56 位的密钥,则可能的密钥数量是 2 的 56 次方个。随着计算机系统能力的不断发展,DES 的安全性比它刚出现时会弱得多,然而从非关键性质的实际出发,仍可以认为它是足够的。不过 ,DES 现在仅用于旧系统的鉴定,而更多地选择新的加密标准 — 高级加密标准(Advanced Encryption Standard,AES)。(PS:对AES的讲述贱鄙人后续讲解,,,呸!不是讲解,是讲述....)

/*****************************************************************************************************************************************/

以上加密过程并不是很复杂,大家需静下心来参考。对于此算法的原理是个什么样,我也不知道了。什么东西要是牵扯到原理,就变的高深起来。

也许,本文说得不够明白清晰或有一些错误,大家可参考其他资料,这是个古老的现代对称密钥加密算法,网上有很多资料的~~



最后,是大家期待已久的代码:(注:本代码是基于文件的加密解密)


#include <stdio.h>
#include <memory.h>
#include <time.h>
#include <stdlib.h>


 
#define PLAIN_FILE_OPEN_ERROR -1
#define KEY_FILE_OPEN_ERROR -2
#define CIPHER_FILE_OPEN_ERROR -3
#define OK 1

typedef char ElemType;

 /*初始置换表IP*/
int 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
};
/*逆初始置换表IP^-1*/
int 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
};
 
/*扩充置换表E*/
int E_Table[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
};
 
/*置换函数P*/
int P_Table[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
};
 
/*Sbox*/
int S[8][4][16] =
{
    /*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}
    }
};
/*置换选择1*/
int PC_1[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
};  
/*置换选择2*/
int PC_2[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,46,43,48,38,55,
    33,52,45,41,49,35,28,31
};
 
/*对左移次数的规定*/
int MOVE_TIMES[16] = {1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1};  

int ByteToBit(ElemType ch,ElemType bit[8]);
int BitToByte(ElemType bit[8],ElemType *ch);
int Char8ToBit64(ElemType ch[8],ElemType bit[64]);
int Bit64ToChar8(ElemType bit[64],ElemType ch[8]);
int DES_MakeSubKeys(ElemType key[64],ElemType subKeys[16][48]);
int DES_PC1_Transform(ElemType key[64], ElemType tempbts[56]);
int DES_PC2_Transform(ElemType key[56], ElemType tempbts[48]);
int DES_ROL(ElemType data[56], int time);
int DES_IP_Transform(ElemType data[64]);
int DES_IP_1_Transform(ElemType data[64]);
int DES_E_Transform(ElemType data[48]);
int DES_P_Transform(ElemType data[32]);
int DES_SBOX(ElemType data[48]);
int DES_XOR(ElemType R[48], ElemType L[48],int count);
int DES_Swap(ElemType left[32],ElemType right[32]);
int DES_EncryptBlock(ElemType plainBlock[8], ElemType subKeys[16][48], ElemType cipherBlock[8]);
int DES_DecryptBlock(ElemType cipherBlock[8], ElemType subKeys[16][48], ElemType plainBlock[8]);
int DES_Encrypt(char *plainFile, char *keyStr,char *cipherFile);
int DES_Decrypt(char *cipherFile, char *keyStr,char *plainFile);  

/*字节转换成二进制*/
int ByteToBit(ElemType ch, ElemType bit[8])
{
    int cnt;
    for(cnt = 0;cnt < 8; cnt++) {
     *(bit + cnt) = (ch >> cnt) & 1;
    }
    
    return 0;
}
 
/*二进制转换成字节*/
int BitToByte(ElemType bit[8], ElemType *ch)
{
    int cnt;
    for(cnt = 0;cnt < 8; cnt++){
        *ch |= *(bit + cnt)<<cnt;
    }
 
    return 0;
}
 
/*将长度为8的字符串转为二进制位串*/
int Char8ToBit64(ElemType ch[8], ElemType bit[64])
{
    int cnt;
    for(cnt = 0; cnt < 8; cnt++){  
        ByteToBit( *(ch + cnt), bit + (cnt << 3) );
    }
 
    return 0;
}
 
/*将二进制位串转为长度为8的字符串*/
int Bit64ToChar8(ElemType bit[64], ElemType ch[8])
{
    int cnt;

    memset(ch, 0, 8);
    for(cnt = 0; cnt < 8; cnt++){
        BitToByte(bit+(cnt<<3), ch+cnt);
    }
    
    return 0;
}
 
/*生成子密钥*/
int DES_MakeSubKeys(ElemType key[64], ElemType subKeys[16][48])
{
    ElemType temp[56];
    int cnt;

    DES_PC1_Transform(key, temp); /*PC1置换*/
    for(cnt = 0; cnt < 16; cnt++) { /*16轮跌代,产生16个子密钥*/
        DES_ROL(temp, MOVE_TIMES[cnt]); /*循环左移*/
        DES_PC2_Transform(temp, subKeys[cnt]); /*PC2置换,产生子密钥*/
    }
 
    return 0;
}
 
/*密钥置换1*/
int DES_PC1_Transform(ElemType key[64], ElemType tempbts[56])
{
    int cnt;

    for(cnt = 0; cnt < 56; cnt++) {
        tempbts[cnt] = key[PC_1[cnt]];
    }
 
    return 0;
}
 
/*密钥置换2*/
int DES_PC2_Transform(ElemType key[56], ElemType tempbts[48])
{
    int cnt;

    for(cnt = 0; cnt < 48; cnt++){
        tempbts[cnt] = key[PC_2[cnt]];
    }
 
    return 0;
}
 
/*循环左移*/
int DES_ROL(ElemType data[56], int time)
{
    ElemType temp[56];
 
    /*保存将要循环移动到右边的位*/
    memcpy(temp, data, time);
    memcpy(temp+time, data+28, time);
 
    /*前28位移动*/
    memcpy(data, data+time, 28-time);
    memcpy(data+28-time, temp, time);
 
    /*后28位移动*/
    memcpy(data+28, data+28+time, 28-time);
    memcpy(data+56-time, temp+time, time);
 
    return 0;
}
 
/*IP置换*/
int DES_IP_Transform(ElemType data[64])
{
    int cnt;
    ElemType temp[64];

    for(cnt = 0; cnt < 64; cnt++){
        temp[cnt] = data[IP_Table[cnt]];
    }
    memcpy(data, temp, 64);
 
    return 0;
}
   
/*IP逆置换*/
int DES_IP_1_Transform(ElemType data[64])
{
    int cnt;
    ElemType temp[64];
    
    for(cnt = 0; cnt < 64; cnt++){
        temp[cnt] = data[IP_1_Table[cnt]];
    }
    memcpy(data,temp,64);
 
    return 0;
}
 
/*扩展置换*/
int DES_E_Transform(ElemType data[48])
{
    int cnt;
    ElemType temp[48];
    for(cnt = 0; cnt < 48; cnt++){
        temp[cnt] = data[E_Table[cnt]];
    }    
    memcpy(data,temp,48);
    
    return 0;
}
 
/*P置换*/
int DES_P_Transform(ElemType data[32])
{
    int cnt;
    ElemType temp[32];
    for(cnt = 0; cnt < 32; cnt++){
        temp[cnt] = data[P_Table[cnt]];
    }
    memcpy(data,temp,32);
    
    return 0;
}
 
/*异或*/
int DES_XOR(ElemType R[48], ElemType L[48], int count)
{
    int cnt;
    for(cnt = 0; cnt < count; cnt++){
        R[cnt] ^= L[cnt];
    }
 
    return 0;
}
 
/*Sbox置换*/
int DES_SBOX(ElemType data[48])
{
    int cnt;
    int line, row, output;
    int cur1, cur2;

    for(cnt = 0; cnt < 8; cnt++) {
        cur1 = cnt * 6;
        cur2 = cnt << 2;
        /*计算在S盒中的行与列*/
        line = (data[cur1]<<1) + data[cur1+5];
        row = (data[cur1+1]<<3) + (data[cur1+2]<<2) + (data[cur1+3]<<1) + data[cur1+4];
        output = S[cnt][line][row];
        /*化为2进制*/
        data[cur2] = (output&0X08)>>3;
        data[cur2+1] = (output&0X04)>>2;
        data[cur2+2] = (output&0X02)>>1;
        data[cur2+3] = output&0x01;
    }
 
    return 0;
}
 
/*交换*/
int DES_Swap(ElemType left[32], ElemType right[32])
{
    ElemType temp[32];

    memcpy(temp,left,32);
    memcpy(left,right,32);  
    memcpy(right,temp,32);
 
    return 0;
}
 
/*加密单个分组*/
int DES_EncryptBlock(ElemType plainBlock[8], ElemType subKeys[16][48], ElemType cipherBlock[8])
{
    ElemType plainBits[64];
    ElemType copyRight[48];
    int cnt;
 
    Char8ToBit64(plainBlock, plainBits);  
    /*初始置换(IP置换)*/
    DES_IP_Transform(plainBits);
 
    /*16轮迭代*/
    for(cnt = 0; cnt < 16; cnt++) {
        memcpy(copyRight, plainBits+32, 32);

        /*将右半部分进行扩展置换,从32位扩展到48位*/
        DES_E_Transform(copyRight);
        /*将右半部分与子密钥进行异或操作,结果保存在函数第一个参数*/
        DES_XOR(copyRight, subKeys[cnt], 48);
        /*异或结果进入S盒,输出32位结果*/
        DES_SBOX(copyRight);
        /*P置换*/
        DES_P_Transform(copyRight);
        /*将明文左半部分与右半部分进行异或*/
        DES_XOR(plainBits, copyRight, 32);
        if(cnt != 15) {
            /*最终完成左右部的交换*/
            DES_Swap(plainBits, plainBits+32);
        }
    }
    /*逆初始置换(IP^-1置换)*/
    DES_IP_1_Transform(plainBits);
    /*将二进制位串转为长度为8的字符串*/
    Bit64ToChar8(plainBits, cipherBlock);

    return 0;
}
 
/*解密单个分组*/
int DES_DecryptBlock(ElemType cipherBlock[8], ElemType subKeys[16][48],ElemType plainBlock[8])
{
    ElemType cipherBits[64];
    ElemType copyRight[48];
    int cnt;
 
    Char8ToBit64(cipherBlock,cipherBits);
    /*初始置换(IP置换)*/
    DES_IP_Transform(cipherBits);
 
    /*16轮迭代*/
    for(cnt = 15; cnt >= 0; cnt--){
        memcpy(copyRight,cipherBits+32,32);
        
        /*将右半部分进行扩展置换,从32位扩展到48位*/
        DES_E_Transform(copyRight);
        /*将右半部分与子密钥进行异或操作*/
        DES_XOR(copyRight,subKeys[cnt],48);  
        /*异或结果进入S盒,输出32位结果*/
        DES_SBOX(copyRight);
        /*P置换*/
        DES_P_Transform(copyRight);  
        /*将明文左半部分与右半部分进行异或*/
        DES_XOR(cipherBits,copyRight,32);
        if(cnt != 0){
            /*最终完成左右部的交换*/
            DES_Swap(cipherBits,cipherBits+32);
        }
    }
    /*逆初始置换(IP^1置换)*/
    DES_IP_1_Transform(cipherBits);
    Bit64ToChar8(cipherBits,plainBlock);
 
    return 0;
}
 
/*加密文件*/
int DES_Encrypt(char *plainFile, char *keyStr, char *cipherFile)
{
    FILE *plain, *cipher;
    int count;
    ElemType plainBlock[8],cipherBlock[8],keyBlock[8];
    ElemType bKey[64];
    ElemType subKeys[16][48];
    
    if((plain = fopen(plainFile,"rb")) == NULL){
        return PLAIN_FILE_OPEN_ERROR;
    }
    if((cipher = fopen(cipherFile,"wb")) == NULL){
        return CIPHER_FILE_OPEN_ERROR;
    }
    /*设置密钥*/
    memcpy(keyBlock, keyStr, 8);
    /*将密钥转换为二进制流*/
    Char8ToBit64(keyBlock, bKey);
    /*生成子密钥*/
    DES_MakeSubKeys(bKey, subKeys);
 
    while(!feof(plain)){
        /*每次读8个字节,并返回成功读取的字节数*/
        if((count = fread(plainBlock, sizeof(char), 8, plain)) == 8){
            DES_EncryptBlock(plainBlock, subKeys, cipherBlock);
            fwrite(cipherBlock, sizeof(char), 8, cipher);  
        }
    }
    if(count){
        /*填充*/
        memset(plainBlock + count, '\0', 7 - count);
        /*最后一个字符保存包括最后一个字符在内的所填充的字符数量*/
        plainBlock[7] = 8 - count;
        DES_EncryptBlock(plainBlock,subKeys,cipherBlock);
        fwrite(cipherBlock,sizeof(char),8,cipher);
    }
    
    fclose(plain);
    fclose(cipher);
 
    return OK;
}
 
/*解密文件*/
int DES_Decrypt(char *cipherFile, char *keyStr,char *plainFile)
{
    FILE *plain, *cipher;
    int count,times = 0;
    long fileLen;

    ElemType plainBlock[8], cipherBlock[8], keyBlock[8];
    ElemType bKey[64];
    ElemType subKeys[16][48];
    if((cipher = fopen(cipherFile,"rb")) == NULL){
        return CIPHER_FILE_OPEN_ERROR;
    }
    if((plain = fopen(plainFile,"wb")) == NULL){
        return PLAIN_FILE_OPEN_ERROR;
    }
 
    /*设置密钥*/
    memcpy(keyBlock,keyStr,8);
    /*将密钥转换为二进制流*/
    Char8ToBit64(keyBlock,bKey);
    /*生成子密钥*/
    DES_MakeSubKeys(bKey,subKeys);
 
    /*取文件长度 */
    fseek(cipher,0,SEEK_END);/*将文件指针置尾*/
    fileLen = ftell(cipher); /*取文件指针当前位置*/
    rewind(cipher); /*将文件指针重指向文件头*/
    while(1) {
        /*密文的字节数一定是8的整数倍*/
        fread(cipherBlock, sizeof(char), 8, cipher);
        DES_DecryptBlock(cipherBlock, subKeys, plainBlock);  
        times += 8;
        if(times < fileLen) {
            fwrite(plainBlock,sizeof(char), 8, plain);
        } else {
            break;
        }
    }
    /*判断末尾是否被填充*/
    if(plainBlock[7] < 8){
        for(count = 8 - plainBlock[7]; count < 7; count++){
            if(plainBlock[count] != '\0'){
                break;
            }
        }
    }
    if(count == 7){/*有填充*/
        fwrite(plainBlock,sizeof(char),8 - plainBlock[7],plain);
    } else{
        /*无填充*/
        fwrite(plainBlock,sizeof(char),8,plain);
    }
    
    fclose(plain);
    fclose(cipher);
    
    return OK;
}

int main (void)
{
     clock_t a,b;
     a = clock();
     DES_Encrypt("1.txt","DESkey00","2.txt");
     b = clock();
     printf("加密消耗%d毫秒\n",b-a);
 
     system("pause");
     a = clock();
     DES_Decrypt("2.txt","DESkey00","3.txt");
     b = clock();
     printf("解密消耗%d毫秒\n",b-a);
     system("pause");
    
     return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值