重慶分公司,新征程啟航
為企業提供網站建設、域名注冊、服務器等服務
為企業提供網站建設、域名注冊、服務器等服務
DES雖然不難但是挺繁復的,代碼如下,關鍵點都有英文解釋,仔細看。各個函數的功能都可以從函數名看出來。
創新互聯建站從2013年成立,先為托克遜等服務建站,托克遜等地企業,進行企業商務咨詢服務。為托克遜企業網站制作PC+手機+微官網三網同步一站式服務解決您的所有建站問題。
#include "pch.h"
#include "misc.h"
#include "des.h"
NAMESPACE_BEGIN(CryptoPP)
/* Tables defined in the Data Encryption Standard documents
* Three of these tables, the initial permutation, the final
* permutation and the expansion operator, are regular enough that
* for speed, we hard-code them. They're here for reference only.
* Also, the S and P boxes are used by a separate program, gensp.c,
* to build the combined SP box, Spbox[]. They're also here just
* for reference.
*/
#ifdef notdef
/* initial permutation IP */
static byte ip[] = {
58, 50, 42, 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
};
/* final permutation IP^-1 */
static byte fp[] = {
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
};
/* expansion operation matrix */
static byte ei[] = {
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
};
/* The (in)famous S-boxes */
static byte sbox[8][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
};
/* 32-bit permutation function P used on the output of the S-boxes */
static byte p32i[] = {
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
};
#endif
/* permuted choice table (key) */
static const byte pc1[] = {
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
};
/* number left rotations of pc1 */
static const byte totrot[] = {
1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28
};
/* permuted choice key (table) */
static const byte pc2[] = {
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
};
/* End of DES-defined tables */
/* bit 0 is left-most in byte */
static const int bytebit[] = {
0200,0100,040,020,010,04,02,01
};
/* Set key (initialize key schedule array) */
DES::DES(const byte *key, CipherDir dir)
: k(32)
{
SecByteBlock buffer(56+56+8);
byte *const pc1m=buffer; /* place to modify pc1 into */
byte *const pcr=pc1m+56; /* place to rotate pc1 into */
byte *const ks=pcr+56;
register int i,j,l;
int m;
for (j=0; j56; j++) { /* convert pc1 to bits of key */
l=pc1[j]-1; /* integer bit location */
m = l 07; /* find bit */
pc1m[j]=(key[l3] /* find which key byte l is in */
bytebit[m]) /* and which bit of that byte */
? 1 : 0; /* and store 1-bit result */
}
for (i=0; i16; i++) { /* key chunk for each iteration */
memset(ks,0,8); /* Clear key schedule */
for (j=0; j56; j++) /* rotate pc1 the right amount */
pcr[j] = pc1m[(l=j+totrot[i])(j28? 28 : 56) ? l: l-28];
/* rotate left and right halves independently */
for (j=0; j48; j++){ /* select bits individually */
/* check bit that goes to ks[j] */
if (pcr[pc2[j]-1]){
/* mask it in if it's there */
l= j % 6;
ks[j/6] |= bytebit[l] 2;
}
}
/* Now convert to odd/even interleaved form for use in F */
k[2*i] = ((word32)ks[0] 24)
| ((word32)ks[2] 16)
| ((word32)ks[4] 8)
| ((word32)ks[6]);
k[2*i+1] = ((word32)ks[1] 24)
| ((word32)ks[3] 16)
| ((word32)ks[5] 8)
| ((word32)ks[7]);
}
if (dir==DECRYPTION) // reverse key schedule order
for (i=0; i16; i+=2)
{
std::swap(k[i], k[32-2-i]);
std::swap(k[i+1], k[32-1-i]);
}
}
/* End of C code common to both versions */
/* C code only in portable version */
// Richard Outerbridge's initial permutation algorithm
/*
inline void IPERM(word32 left, word32 right)
{
word32 work;
work = ((left 4) ^ right) 0x0f0f0f0f;
right ^= work;
left ^= work 4;
work = ((left 16) ^ right) 0xffff;
right ^= work;
left ^= work 16;
work = ((right 2) ^ left) 0x33333333;
left ^= work;
right ^= (work 2);
work = ((right 8) ^ left) 0xff00ff;
left ^= work;
right ^= (work 8);
right = rotl(right, 1);
work = (left ^ right) 0xaaaaaaaa;
left ^= work;
right ^= work;
left = rotl(left, 1);
}
inline void FPERM(word32 left, word32 right)
{
word32 work;
right = rotr(right, 1);
work = (left ^ right) 0xaaaaaaaa;
left ^= work;
right ^= work;
left = rotr(left, 1);
work = ((left 8) ^ right) 0xff00ff;
right ^= work;
left ^= work 8;
work = ((left 2) ^ right) 0x33333333;
right ^= work;
left ^= work 2;
work = ((right 16) ^ left) 0xffff;
left ^= work;
right ^= work 16;
work = ((right 4) ^ left) 0x0f0f0f0f;
left ^= work;
right ^= work 4;
}
*/
// Wei Dai's modification to Richard Outerbridge's initial permutation
// algorithm, this one is faster if you have access to rotate instructions
// (like in MSVC)
inline void IPERM(word32 left, word32 right)
{
word32 work;
right = rotl(right, 4U);
work = (left ^ right) 0xf0f0f0f0;
left ^= work;
right = rotr(right^work, 20U);
work = (left ^ right) 0xffff0000;
left ^= work;
right = rotr(right^work, 18U);
work = (left ^ right) 0x33333333;
left ^= work;
right = rotr(right^work, 6U);
work = (left ^ right) 0x00ff00ff;
left ^= work;
right = rotl(right^work, 9U);
work = (left ^ right) 0xaaaaaaaa;
left = rotl(left^work, 1U);
right ^= work;
}
inline void FPERM(word32 left, word32 right)
{
word32 work;
right = rotr(right, 1U);
work = (left ^ right) 0xaaaaaaaa;
right ^= work;
left = rotr(left^work, 9U);
work = (left ^ right) 0x00ff00ff;
right ^= work;
left = rotl(left^work, 6U);
work = (left ^ right) 0x33333333;
right ^= work;
left = rotl(left^work, 18U);
work = (left ^ right) 0xffff0000;
right ^= work;
left = rotl(left^work, 20U);
work = (left ^ right) 0xf0f0f0f0;
right ^= work;
left = rotr(left^work, 4U);
}
// Encrypt or decrypt a block of data in ECB mode
void DES::ProcessBlock(const byte *inBlock, byte * outBlock) const
{
word32 l,r,work;
#ifdef IS_LITTLE_ENDIAN
l = byteReverse(*(word32 *)inBlock);
r = byteReverse(*(word32 *)(inBlock+4));
#else
l = *(word32 *)inBlock;
r = *(word32 *)(inBlock+4);
#endif
IPERM(l,r);
const word32 *kptr=k;
for (unsigned i=0; i8; i++)
{
work = rotr(r, 4U) ^ kptr[4*i+0];
l ^= Spbox[6][(work) 0x3f]
^ Spbox[4][(work 8) 0x3f]
^ Spbox[2][(work 16) 0x3f]
^ Spbox[0][(work 24) 0x3f];
work = r ^ kptr[4*i+1];
l ^= Spbox[7][(work) 0x3f]
^ Spbox[5][(work 8) 0x3f]
^ Spbox[3][(work 16) 0x3f]
^ Spbox[1][(work 24) 0x3f];
work = rotr(l, 4U) ^ kptr[4*i+2];
r ^= Spbox[6][(work) 0x3f]
^ Spbox[4][(work 8) 0x3f]
^ Spbox[2][(work 16) 0x3f]
^ Spbox[0][(work 24) 0x3f];
work = l ^ kptr[4*i+3];
r ^= Spbox[7][(work) 0x3f]
^ Spbox[5][(work 8) 0x3f]
^ Spbox[3][(work 16) 0x3f]
^ Spbox[1][(work 24) 0x3f];
}
FPERM(l,r);
#ifdef IS_LITTLE_ENDIAN
*(word32 *)outBlock = byteReverse(r);
*(word32 *)(outBlock+4) = byteReverse(l);
#else
*(word32 *)outBlock = r;
*(word32 *)(outBlock+4) = l;
#endif
}
void DES_EDE_Encryption::ProcessBlock(byte *inoutBlock) const
{
e.ProcessBlock(inoutBlock);
d.ProcessBlock(inoutBlock);
e.ProcessBlock(inoutBlock);
}
void DES_EDE_Encryption::ProcessBlock(const byte *inBlock, byte *outBlock) const
{
e.ProcessBlock(inBlock, outBlock);
d.ProcessBlock(outBlock);
e.ProcessBlock(outBlock);
}
void DES_EDE_Decryption::ProcessBlock(byte *inoutBlock) const
{
d.ProcessBlock(inoutBlock);
e.ProcessBlock(inoutBlock);
d.ProcessBlock(inoutBlock);
}
void DES_EDE_Decryption::ProcessBlock(const byte *inBlock, byte *outBlock) const
{
d.ProcessBlock(inBlock, outBlock);
e.ProcessBlock(outBlock);
d.ProcessBlock(outBlock);
}
void TripleDES_Encryption::ProcessBlock(byte *inoutBlock) const
{
e1.ProcessBlock(inoutBlock);
d.ProcessBlock(inoutBlock);
e2.ProcessBlock(inoutBlock);
}
void TripleDES_Encryption::ProcessBlock(const byte *inBlock, byte *outBlock) const
{
e1.ProcessBlock(inBlock, outBlock);
d.ProcessBlock(outBlock);
e2.ProcessBlock(outBlock);
}
void TripleDES_Decryption::ProcessBlock(byte *inoutBlock) const
{
d1.ProcessBlock(inoutBlock);
e.ProcessBlock(inoutBlock);
d2.ProcessBlock(inoutBlock);
}
void TripleDES_Decryption::ProcessBlock(const byte *inBlock, byte *outBlock) const
{
d1.ProcessBlock(inBlock, outBlock);
e.ProcessBlock(outBlock);
d2.ProcessBlock(outBlock);
}
#includeiostream.h
class SubKey{ //定義子密鑰為一個類
public:
int key[8][6];
}subkey[16]; //定義子密鑰對象數組
class DES{
int encipher_decipher; //判斷加密還是解密
int key_in[8][8]; //用戶原始輸入的64位二進制數
int key_out[8][7]; //除去每行的最后一位校驗位
int c0_d0[8][7]; //存儲經PC-1轉換后的56位數據
int c0[4][7],d0[4][7]; //分別存儲c0,d0
int text[8][8]; //64位明文
int text_ip[8][8]; //經IP轉換過后的明文
int A[4][8],B[4][8]; //A,B分別存儲經IP轉換過后明文的兩部分,便于交換
int temp[8][6]; //存儲經擴展置換后的48位二進制值
int temp1[8][6]; //存儲和子密鑰異或后的結果
int s_result[8][4]; //存儲經S變換后的32位值
int text_p[8][4]; //經P置換后的32位結果
int secret_ip[8][8]; //經逆IP轉換后的密文
public:
void Key_Putting();
void PC_1();
int function(int,int); //異或
void SubKey_Production();
void IP_Convert();
void f();
void _IP_Convert();
void Out_secret();
};
void DES::Key_Putting() //得到密鑰中對算法有用的56位
{
cout"請輸入64位的密鑰(8行8列且每行都得有奇數個1):\n";
for(int i=0;i8;i++)
for(int j=0;j8;j++){
cinkey_in[i][j];
if(j!=7) key_out[i][j]=key_in[i][j];
}
}
void DES::PC_1() //PC-1置換函數
{
int pc_1[8][7]={ //PC-1
{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}
};
int i,j;
for(i=0;i8;i++)
for(j=0;j7;j++)
c0_d0[i][j]=key_out[ (pc_1[i][j]-1)/8 ][ (pc_1[i][j]-1)%8 ];
}
int DES::function(int a,int b) //模擬二進制數的異或運算,a和b為整型的0和1,返回值為整型的0或1
{
if(a!=b)return 1;
else return 0;
}
void DES::SubKey_Production() //生成子密鑰
{
int move[16][2]={ //循環左移的位數
1 , 1 , 2 , 1 ,
3 , 2 , 4 , 2 ,
5 , 2 , 6 , 2 ,
7 , 2 , 8 , 2 ,
9 , 1, 10 , 2,
11 , 2, 12 , 2,
13 , 2, 14 , 2,
15 , 2, 16 , 1
};
int pc_2[8][6]={ //PC-2
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
};
for(int i=0;i16;i++) //生成子密鑰
{
int j,k;
int a[2],b[2];
int bb[28],cc[28];
for(j=0;j4;j++)
for(k=0;k7;k++)
c0[j][k]=c0_d0[j][k];
for(j=4;j8;j++)
for(k=0;k7;k++)
d0[j-4][k]=c0_d0[j][k];
for(j=0;j4;j++)
for(k=0;k7;k++){
bb[7*j+k]=c0[j][k];
cc[7*j+k]=d0[j][k];
}
for(j=0;jmove[i][1];j++){
a[j]=bb[j];
b[j]=cc[j];
}
for(j=0;j28-move[i][1];j++){
bb[j]=bb[j+1];
cc[j]=cc[j+1];
}
for(j=0;jmove[i][1];j++){
bb[27-j]=a[j];
cc[27-j]=b[j];
}
for(j=0;j28;j++){
c0[j/7][j%7]=bb[j];
d0[j/7][j%7]=cc[j];
}
for(j=0;j4;j++) //L123--L128是把c0,d0合并成c0_d0
for(k=0;k7;k++)
c0_d0[j][k]=c0[j][k];
for(j=4;j8;j++)
for(k=0;k7;k++)
c0_d0[j][k]=d0[j-4][k];
for(j=0;j8;j++) //對Ci,Di進行PC-2置換
for(k=0;k6;k++)
subkey[i].key[j][k]=c0_d0[ (pc_2[j][k]-1)/7 ][ (pc_2[j][k]-1)%7 ];
}
}
void DES::IP_Convert()
{
int IP[8][8]={ //初始置換IP矩陣
58, 50, 42, 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
};
cout"你好,你要加密還是解密?加密請按1號鍵(輸入1),解密請按2號鍵,并確定."'\n';
cinencipher_decipher;
char * s;
if(encipher_decipher==1) s="明文";
else s="密文";
cout"請輸入64位"s"(二進制):\n";
int i,j;
for(i=0;i8;i++)
for(j=0;j8;j++)
cintext[i][j];
for(i=0;i8;i++) //進行IP變換
for(j=0;j8;j++)
text_ip[i][j]=text[ (IP[i][j]-1)/8 ][ (IP[i][j]-1)%8 ];
}
using system;
using system.security.cryptography;
using system.io;
using system.text;
public class encryptstringdes {
public static void main(string);
return;
}
// 使用utf8函數加密輸入參數
utf8encoding utf8encoding = new utf8encoding();
byte.tochararray());
// 方式一:調用默認的des實現方法des_csp.
des des = des.create();
// 方式二:直接使用des_csp()實現des的實體
//des_csp des = new des_csp();
// 初始化des加密的密鑰和一個隨機的、8比特的初始化向量(iv)
byte iv = {0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef};
des.key = key;
des.iv = iv;
// 建立加密流
symmetricstreamencryptor sse = des.createencryptor();
// 使用cryptomemorystream方法獲取加密過程的輸出
cryptomemorystream cms = new cryptomemorystream();
// 將symmetricstreamencryptor流中的加密數據輸出到cryptomemorystream中
sse.setsink(cms);
// 加密完畢,將結果輸出到控制臺
sse.write(inputbytearray);
sse.closestream();
// 獲取加密數據
byte);
}
console.writeline();
//上面演示了如何進行加密,下面演示如何進行解密
symmetricstreamdecryptor ssd = des.createdecryptor();
cms = new cryptomemorystream();
ssd.setsink(cms);
ssd.write(encrypteddata);
ssd.closestream();
byte decryptedchararray = utf8encoding.getchars(decrypteddata);
console.writeline("解密后數據:");
console.write(decryptedchararray);
console.writeline();
}
}
編譯:
d:\csharpcsc des_demo.cs
microsoft (r) c# compiler version 7.00.8905
copyright (c) microsoft corp 2000. all rights reserved.
運行實例:
d:\csharpdes_demo.exe 使用c#編寫des加密程序的framework
加密結果:
3d 22 64 c6 57 d1 c4 c3 cf 77 ce 2f d0 e1 78 2a 4d ed 7a a8 83 f9 0e 14 e1 ba 38
7b 06 41 8d b5 e9 3f 00 0d c3 28 d1 f9 6d 17 4b 6e a7 41 68 40