视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
实验一 加密算法
2025-10-03 06:40:32 责编:小OO
文档
实验一  加密算法

1、实验背景   

●多表替代密码:由多个简单的替代密码构成,例如,可能有5个不同的简单替代密码,分别用于替代明文中不同位置的字符。主要学习维吉尼亚表。

●换位密码:一种早期的加密方法,明文的字母保持相同,但顺序被打乱了。

●DES加密算法工作的基本原理:其入口参数有三个:key、data、mode。 key为加密解密使用的密钥,data为加密解密的数据,mode为其工作模式。当模式为加密模式时,明文按照位进行分组,形成明文组,key用于对数据加密,当模式为解密模式时,key用于对数据解密。实际运用中,密钥只用到了位中的56位,这样才具有高的安全性。主要掌握S盒替代。

2、实验目的

    1、实验课前复习DES加密、传统加密算法—多表替代(维吉尼亚表替代)、换位密码算法。

2、任选C、C++、VC++等其中一种来实现编程实现加密算法。

    3、调试程序,给定一段明文,和密钥,通过加密算法,给出密文。

    4、目的:掌握加密算法的基本原理及其加密方法的详细步骤。

3、实验所需设备

安装Windows9x/2000/XP/2003操作系统和Visualstudio 6.0环境的PC。 

4、实验拓扑 

   无

5 、实验步骤

●多表替代 注意红色字体代码

    1  启动VC++6.0。

    2  新建Win32 Console Application。

    3  在Project Name和Locate位置填上工程名weijiniya和保存位置(自选)。

    4  按OK按钮。选An simple Project。

5  按Finish按钮。

6  在weijiniya.cpp中添加如下代码:

 #include "stdafx.h"

#include

#include

#include

#include

void Shift() /*移位密码*/ 

char c[100]; 

int length, i=0, key=0; 

//clrscr(); 

printf("********Shift Cipher********\\nPlease input primal sentence: "); 

gets(c); 

length = strlen(c); 

printf("Input the key(0~26): "); 

scanf("%d", &key); 

getchar(); 

if(key<0)

printf("The value of key is error!\\nPress any key to return..."); 

getch(); 

return; 

for(i=0; i

if(c[i]>96&&c[i]<123)

c[i] = (c[i]+key-97)%26+65; 

else if(c[i]>&&c[i]<91)

c[i] = (c[i]+key-65)%26+65; 

printf("Result is: %s\\n", c); 

for(i=0; i

if(c[i]>&&c[i]<91)

c[i] = (c[i]-key-65+26)%26+97; 

printf("\\nAfter translated the sentence,we can see the primal sentence as follow:\\n%s\\n", c); 

printf("Press any key to return..."); 

getch(); 

int (int a, int b) /*辗转相除法求a,b的最大公因数*/ 

int k = 0; 

do 

k = a%b; 

a = b; 

b = k; 

}while(k!=0); 

return a; 

int Ni(int a, int b) /*求a相对于b的逆*/ 

int i = 0; 

while(a*(++i)%b!=1); 

return i; 

void Affine() /*仿射密码*/ 

char c[100]; 

int length, i=0, ka=0, kb=0, tmp; 

//clrscr(); 

printf("********Affine Cipher********\\nPlease input primal sentence: "); 

gets(c); 

length = strlen(c); 

printf("Input the key(2 numbers): "); 

scanf("%d%d", &ka, &kb); 

getchar(); 

if((ka,26)!=1) 

printf("The value of the key is error!\\nPress any key to return..."); 

return; 

for(i=0; i

if(c[i]>96&&c[i]<123)

c[i] = (ka*(c[i]-97)+kb)%26+65; 

else if(c[i]>&&c[i]<91)

c[i] = (ka*(c[i]-65)+kb)%26+65; 

printf("Result is: %s\\n", c); 

for(i=0; i

if(c[i]>&&c[i]<91)

tmp = Ni(ka,26)*((c[i]-65)-kb); 

if(tmp<0)

c[i] = tmp%26+26+97; 

else 

c[i] = tmp%26+97; 

printf("\\nAfter translated the sentence,we can see the primal sentence as follow:\\n%s\\n", c); 

printf("Press any key to return..."); 

getch(); 

void Vigenere() /*维吉利亚密码*/ 

char c[100], key[100]; 

int lenc, lenk, i=0, j=0, tmp; 

//clrscr(); 

printf("********Vigenere Cipher********\\nPlease input primal sentence: "); 

gets(c); 

lenc = strlen(c); 

strcpy(c, strupr(c)); 

printf("Input the key: "); 

gets(key); 

lenk = strlen(key); 

strcpy(key, strupr(key)); 

for(; i

j = j%lenk; 

if(c[i]>&&c[i]<91)

c[i] = (c[i]-65+key[j]-65)%26+65; 

j++; 

printf("Result is: %s\\n", c); 

for(i=0, j=0; i

j = j%lenk; 

if(c[i]>&&c[i]<91)

tmp = c[i]-65-(key[j]-65); 

if(tmp>=0)

c[i] = tmp%26+97; 

else 

c[i] = (tmp+26)%26+97; 

j++; 

printf("\\nAfter translated the sentence,we can see the primal sentence as follow:\\n%s\\n", c); 

printf("Press any key to return..."); 

getch(); 

void Permutation() /*置换密码*/ 

char c[100], *q; 

int *key, len, m, i, j=0; 

//clrscr(); 

printf("********Permutation Cipher********\\nPlease input primal sentence: "); 

gets(c); 

strcpy(c, strupr(c)); 

len = strlen(c); 

for(i=0; i

if(c[i]<65||c[i]>90)

for(j=i; jc[j] = c[j+1]; 

len--; 

c[len] = '\\0'; 

printf("Input the length of the key: "); 

scanf("%d", &m); 

//key = (int)new(m*sizeof(int)); 

//q = (int)new(len*sizeof(int)); 

printf("Input the key: "); 

for(i=0; i

scanf("%d", key+i); 

key[i]--; 

getchar(); 

for(i=0; i

j = (i/m)*m; 

q[i] = c[*(key+i%m)+j]; 

q[i] = '\\0'; 

printf("Result is: %s\\n", q); 

for(i=0, j=0; i

j = (i/m)*m; 

c[*(key+i%m)+j] = q[i]+32; 

c[len] = '\\0'; 

printf("After translated the sentence,we can see the primal sentence as follow:\\n%s\\n", c); 

printf("Press any key to return..."); 

free(key); 

free(q); 

getch(); 

int main(int argc, char* argv[])

{

char i = '0'; 

//clrscr(); 

while(i!='5') 

//clrscr(); 

printf("********Press 1~5 to choose:********\\n"); 

printf("1. Shift Cipher\\n2. Affine Cipher\\n3. Vigenere Cipher\\n4. Permutation Cipher\\n5. Exit\\n"); 

i = getch(); 

if(i=='1') 

Shift(); 

else if(i=='2') 

Affine(); 

else if(i=='3') 

Vigenere(); 

else if(i=='4') 

Permutation(); 

else if(i=='5') 

break; 

return 0;

}

7  按运行按钮,看编译运行结果,如图1-1所示:

图1-1 加密运行界面

8 选择3,按如1-2所示,输入明文和密钥,调试输出对应加密密文。

图1-2 选择维吉尼亚加密方法

●换位密码

1  启动VC++6.0。

    2  新建Win32 Console Application。

    3  在Project Name和Locate位置填上工程名string和保存位置(自选)。

    4  按OK按钮。选An simple Project。

5  按Finish按钮。

6  在string.cpp中添加如下代码:

#include "stdafx.h"

#include

#include

int main(int argc, char * argv[])//注释加密程序,解密程序类同,不重复

{

 char a[80];

 int k,i;

 printf("请输入移位值K和明文(小写字母,以'#'结束):\n");

 scanf("%d\\n",&k);//输入密码K

if(k>26)//移位超出26时,相当于重复循环

  k=k%26;

for(i=0;i<80;i++)

 {

  scanf("%c",&a[i]);//输入明文

  if(a[i]=='#')break;

 }

 printf("密文如下:\n");

 for(i=0;a[i]!='#';i++)

 {

if(a[i]<97||a[i]>122)

  {

   printf("移位值K格式出错或明文输入错误,无法显示密文!退出!\n");

   return 0;

  }

 }

 for(i=0;a[i]!='#';i++)

 {

if(k>0)

  {

   a[i]=a[i]-32;

if(k>90-a[i])

    a[i]=65+(k-(90-a[i]))-1;

       

   else

    a[i]=a[i]+k;//非循环情况是转换成大写后,加上移位密码即可

  }

  else

  {

   k=-k;

if(k>26)//移位超出26时,相当于重复循环

    k=k%26;

   a[i]=a[i]-32;

if(k>a[i]-65)

    a[i]=90-(k-(a[i]-65))-1;

   else

    a[i]=a[i]-k;

   k=-k;

  }

  printf("%c",a[i]);

 }

 printf("\\n");

   

 k=0;

 printf("请输入移位值K和密文(大写字母,以'#'结束):\n");

 scanf("%d\\n",&k);

if(k>26)

  k=k%26;

for(i=0;i<80;i++)

 {

  scanf("%c",&a[i]);

  if(a[i]=='#')break;

 }

 printf("明文如下:\n");

 for(i=0;a[i]!='#';i++)

 {

if(a[i]<65||a[i]>90)

  {

   printf("移位值K格式出错或密文输入错误,无法显示明文!退出!\n");

   return 0;

  }

 }

 for(i=0;a[i]!='#';i++)

 {

if(k>0)

  {

   a[i]=a[i]+32;

if(k>a[i]-97)

    a[i]=122-(k-(a[i]-97))+1;

   else

    a[i]=a[i]-k;

  }

  else

  { 

   k=-k;

if(k>26)

    k=k%26;

   a[i]=a[i]+32;

if(k>122-a[i])

    a[i]=97+(k-(122-a[i]))+1;

   else

    a[i]=a[i]+k;

   k=-k;

  }

  printf("%c",a[i]);

 }

 printf("\\n");

 getch();

return 0;

}

换位密码运行结果如图1-3所示:

加密——移位k=2,明文:abc

解密——移位K=2,密文CDE

图1-3 换位密码运行结果

●DES加密算法——S盒替代 注意红色字体代码

步骤同多表替代密码。工程名为DESLxp,在DES.cpp中添加如下代码:

#include "stdafx.h"

#include "DESlxp.h"

#include "DES.h"

#ifdef _DEBUG

#undef THIS_FILE

static char THIS_FILE[]=__FILE__;

#define new DEBUG_NEW

#endif

//////////////////////////////////////////////////////////////////// Construction/Destruction

//////////////////////////////////////////////////////////////////DES::DES()

{

}

DES::~DES()

{

}

// initial permutation IP

const static char IP_Table[] = {

    58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4,

    62, 54, 46, 38, 30, 22, 14, 6, , 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 

const static char IPR_Table[] = {

    40, 8, 48, 16, 56, 24, , 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 const char E_Table[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

};

// 32-bit permutation function P used on the output of the S-boxes 

const static char P_Table[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

};

// permuted choice table (key) 

const static char PC1_Table[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

};

// permuted choice key (table) 

const static char PC2_Table[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};

// number left rotations of pc1 

const static char LOOP_Table[16] = {

    1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1};

// The (in)famous S-boxes 

const static char S_Box[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

};

//////////////////////////////////////////////////////////////////typedef bool    (*PSubKey)[16][48];

//////////////////////////////////////////////////////////////////static void SDES(char Out[8], char In[8], const PSubKey pSubKey, bool Type);//标准DES加/解密

static void SetKey(const char* Key, int len);// 设置密钥

static void SetSubKey(PSubKey pSubKey, const char Key[8]);// 设置子密钥

static void F_func(bool In[32], const bool Ki[48]);// f 函数

static void S_func(bool Out[32], const bool In[48]);// S 盒代替

static void Transform(bool *Out, bool *In, const char *Table, int len);// 变换

static void Xor(bool *InA, const bool *InB, int len);// 异或

static void RotateL(bool *In, int len, int loop);// 循环左移

static void ByteToBit(bool *Out, const char *In, int bits);// 字节组转换成位组

static void BitToByte(char *Out, const bool *In, int bits);// 位组转换成字节组

//////////////////////////////////////////////////////////////////static bool SubKey[2][16][48];// 16圈子密钥

static bool Is3DES;// 3次DES标志

static char Tmp[256], deskey[16];

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Code starts from Line 130

//////////////////////////////////////////////////////////////////void SetKey(const char* Key, int len)

{

    memset(deskey, 0, 16);

memcpy(deskey, Key, len>16?16:len);

    SetSubKey(&SubKey[0], &deskey[0]);

Is3DES = len>8 ? (SetSubKey(&SubKey[1], &deskey[8]), true) : false;

}

void SDES(char Out[8], char In[8], const PSubKey pSubKey, bool Type)

{

    static bool M[], tmp[32], *Li=&M[0], *Ri=&M[32];

    ByteToBit(M, In, );

    Transform(M, M, IP_Table, );

    if( Type == ENCRYPT ){

for(int i=0; i<16; ++i) {

            memcpy(tmp, Ri, 32);

            F_func(Ri, (*pSubKey)[i]);

            Xor(Ri, Li, 32);

            memcpy(Li, tmp, 32);

        }

    }else{

for(int i=15; i>=0; --i) {

            memcpy(tmp, Li, 32);

            F_func(Li, (*pSubKey)[i]);

            Xor(Li, Ri, 32);

            memcpy(Ri, tmp, 32);

        }

    }

    Transform(M, M, IPR_Table, );

    BitToByte(Out, M, );

}

void SetSubKey(PSubKey pSubKey, const char Key[8])

{

    static bool K[], *KL=&K[0], *KR=&K[28];

    ByteToBit(K, Key, );

    Transform(K, K, PC1_Table, 56);

for(int i=0; i<16; ++i) {

        RotateL(KL, 28, LOOP_Table[i]);

        RotateL(KR, 28, LOOP_Table[i]);

        Transform((*pSubKey)[i], K, PC2_Table, 48);

    }

}

void F_func(bool In[32], const bool Ki[48])

{

    static bool MR[48];

    Transform(MR, In, E_Table, 48);

    Xor(MR, Ki, 48);

    S_func(In, MR);

    Transform(In, In, P_Table, 32);

}

void S_func(bool Out[32], const bool In[48])

{

for(char i=0,j,k; i<8; ++i,In+=6,Out+=4) {

j = (In[0]<<1) + In[5];

k = (In[1]<<3) + (In[2]<<2) + (In[3]<<1) + In[4];

        ByteToBit(Out, &S_Box[i][j][k], 4);

    }

}

void Transform(bool *Out, bool *In, const char *Table, int len)

{

for(int i=0; i        Tmp[i] = In[ Table[i]-1 ];

    memcpy(Out, Tmp, len);

}

void Xor(bool *InA, const bool *InB, int len)

{

for(int i=0; i        InA[i] ^= InB[i];

}

void RotateL(bool *In, int len, int loop)

{

    memcpy(Tmp, In, loop);

    memcpy(In, In+loop, len-loop);

    memcpy(In+len-loop, Tmp, loop);

}

void ByteToBit(bool *Out, const char *In, int bits)

{

for(int i=0; i Out[i] = (In[i>>3]>>(i&7)) & 1;

}

void BitToByte(char *Out, const bool *In, int bits)

{

memset(Out, 0, bits>>3);

for(int i=0; i Out[i>>3] |= In[i]<<(i&7);

}

bool DES::Des_Go(char *Out, char *In, long datalen, const char *Key, int keylen, bool Type)

{

if( !( Out && In && Key && (datalen=(datalen+7)&0xfffffff8) ) ) 

        return false;

    SetKey(Key, keylen);

    if( !Is3DES ) {   // 1次DES

        for(long i=0,j=datalen>>3; i            SDES(Out, In, &SubKey[0], Type);

    } else{   // 3次DES 加密:加(key0)-解(key1)-加(key0) 解密::解(key0)-加(key1)-解(key0)

        for(long i=0,j=datalen>>3; i            SDES(Out, In,  &SubKey[0], Type);

            SDES(Out, Out, &SubKey[1], !Type);

            SDES(Out, Out, &SubKey[0], Type);

        }

    }

    return true;

}

DES运行结果如图1-4所示:(提示:本次实验解密以8位明文进行加密为例)

图1-4 DES加密运行结果

五 、思考题

1、DES算法主要有哪几部分?

2、DES加密算法中S盒替代原理是什么?

3、维吉尼亚多表替代算法原理是什么?

4、写出采用维吉尼亚算法加密解密实验结果样例。(不允许跟实验指导书重复)

5、写出换位密码加密解密实验结果样例。(不允许跟实验指导书重复)下载本文

显示全文
专题