c语言程序设计实验与案例答案_密码学应用

c语言程序设计实验与案例答案_密码学应用

目录

一、实验目的

二、实验内容

三、实验过程

1.概要设计

(1)随机全排列生成程序

(2)程序逻辑图

2.详细设计

(1)密钥字法

(2)洗牌法

(3)公式法

(4)自设计随机16全排列

(5)生成密码本(unsigned char *KeyGen)

(6)源代码

3.测试结果

(1)替换密码

(2)移位密码

4.遇到问题

四、实验体会

五、思考题


密码学实验一、二

随机全排列生成程序极其应用开发

两种基本古典密码设计与实现

一、实验目的

该实验为验证性实验。

通过本实验,使学生对于两种基本的古典密码编码方法(“代替”与“移位”)产生深刻的感性认识,体验清楚二者之间的本质差异,为理解和掌握现代密码的相应知识打下良好基础。

二、实验内容

1. 设计一个周期3的多表代替密码并予以实现,要求:第1个表由密钥字法产生(密钥字自拟),第2个表由洗牌法产生(注意,字母a~z与数字0~25对应,洗牌法即相当于实验一的方法1(n=25)),第三个表由公式法产生(数学公式自拟,注意它须是Z26上的一个一一变换)。

2.设计一个周期5的16-置换移位密码并予以实现,要求:5个16-置换至少有一个是由实验一(n=15)提供的两个方法以外、自行设计的其它方法产生。

三、实验过程

1.概要设计

说明本程序中用到的所有数据结构的定义、主程序的流程以及程序模块之间的层次(调用)关系。可用流程图等图形化工具描述,并辅以对各模块功能的必要说明。

(1)随机全排列生成程序

方法1:读取一个随机文件中n+1字节数据存入d,对0~n的自然排列,从i=n开始,计算j=(d[i-1]+d[i])%i ,并交换P[i]与P[j]的值。

程序设计: 

unsigned char *full_array1(int n) {     int i,j;     char filename[20];     FILE *fp;     static unsigned char d[256],P[256],temp;     start:         printf("\n 请输入随机数据采样文件名:\n");         scanf("%s",filename);         if( (fp=fopen(filename,"rb"))==NULL )         {             printf("没有找到文件:%s\n",filename);             goto start;         }     fread(d,n+1,1,fp);     fclose(fp);     for(i=0;i<=n;i++)     {         P[i] = i ; //形成自然排列     }     for(i=n;i>0;i--)     {         j=(d[i-1]+d[i])%i ;         temp = P[i] ;         P[i] = P[j];         P[j] = temp; //交换     }     return(P); }

​​​​​​​方法2:随机函数生成一串,依次mod n,并入排列,并将重复的删去,直到生成0~n的随机全排列。

程序设计:

unsigned char *full_array2(int n) {     int m, i, j, k, l=0, flag;     static unsigned char P[256];     start:         printf("\n请输入不小于%d的所用随机数个数:\n", n+1);         scanf("%d",&m);         if(m<=n)         {           printf("\n输入数%d比%d小,须重新输入!\n", m, n+1);                 goto start;         }         srand((unsigned)time(NULL));         for(i=0;i<m;i++)         {             P[l++]=(unsigned char)(rand()%(n+1));             for(j=0;j<l-1;j++)             {                 if(P[j]==P[l-1])                 {                     l--;                     break;                 }             }         }         k=l;         for(i=0;i<=n;i++)         {             flag=0;             for(j=0;j<k;j++)             {                 if(P[j]==i)                 {                     flag=l;                     break;                 }             }             if(!flag)             {                 P[l]=i;                 l++;             }         }         return (P); }

(2)程序逻辑图

主函数(题目一):

c语言程序设计实验与案例答案_密码学应用(题目二相似)

KeyGen_s函数(生成密码本):

c语言程序设计实验与案例答案_密码学应用

2.详细设计

(1)密钥字法

原理:首先选择一个便于记忆的字母串作为密钥字,然后删去密钥字中重复字母,接下来用余下字母顺序添加至密钥之后,形成全新26字母排序。

举例:以密钥为hello为例,下图为该密钥生成密码本。

a

b

c

d

e

f

g

h

i

j

k

l

m

n

o

p

q

r

s

t

u

v

w

x

y

z

h

e

l

o

a

b

c

d

f

g

i

j

k

m

n

p

q

r

s

t

u

v

w

x

y

z

以密钥为abcabc为例,下图为该密钥生成密码本。

a

b

c

d

e

f

g

h

i

j

k

l

m

n

o

p

q

r

s

t

u

v

w

x

y

z

a

b

c

d

e

f

g

h

i

j

k

l

m

n

o

p

q

r

s

t

u

v

w

x

y

z

程序设计:

printf("\n请输入密钥字:\n"); gets(KeyWords); strcat(KeyWords,"abcdefghijklmnopqrstuvwxyz"); k=0; l=strlen(KeyWords); ChoiceWords[k]=tolower(KeyWords[0]); for(i=1;i<l;i++) { if(letter_to_digit(KeyWords[i])==-1) { continue; } ChoiceWords[++k]=tolower(KeyWords[i]); for(j=0;j<k;j++) { if(ChoiceWords[j]==ChoiceWords[k]) { k--; break; } } } for(i=0;i<26;i++) { KeyTab[i]=(unsigned char)letter_to_digit(ChoiceWords[i]); }

(2)洗牌法

原理:就是将写有0~(n-1)的n张纸牌打乱次序后重新排列。打乱次序的方式利用(1)随机全排列生成程序。

程序设计:

p=full_array1(25);                         //生成随机全排列   for(i=0;i<26;i++)KeyTab[26+i]=p[i];   //密码本27~52(抽牌法)

(3)公式法

原理:利用公式生成密码表。公式为(11*i+3)mod 26

程序设计:

for(i=0;i<26;i++) KeyTab[52+i]=(unsigned char)((11*i+3)%26);//密码本53~78        

(4)自设计随机16全排列

原理:

unsigned char *full_array16_pickout(){ //自己写的创建随机16全排列,抽牌法       int i,j,l;       static unsigned char p[256];       while(l<16){           p[l++]=(unsigned char)(rand()%16);           for(j=0;j<l-1;j++){               if(p[j]==p[l-1]){                   l--;                   break;               }           }       }       static unsigned char pout[256];       l=15,i=0;       while(l>=0){           j=rand()%16;           pout[i++]=p[j];           p[j]=p[l--];       }       return pout;   }

(5)生成密码本(unsigned char *KeyGen)

     原理:该函数生成密码本本质上是一个78长的数组。前26位存储密钥字法生成的字母序列;中间26位存储抽牌法生成的字母序列;最后26位储存公式法生成序列。

以下为周期3替代密码表。

a

b

c

d

e

f

g

h

i

j

k

l

m

n

o

p

q

r

s

t

u

v

w

x

y

z

密钥字

抽牌

公式

生成五组随机数,构成5-16置换密码表。

0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

(6)源代码

在编写代码过程中,部分函数参考实验指导书,主函数

题目一:

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <time.h> #include <unistd.h> unsigned char *KeyGen_s(); unsigned char *full_array1(int n); int letter_to_digit(char c); char digit_to_letter(int n); void Encrypt_s(unsigned char *key); int main() {     unsigned char *key;     key=KeyGen_s();  printf("\n以下为生成密码本:\n");     for(int i=0;i<3;i++){ for(int j=0;j<26;j++){ putchar(digit_to_letter(key[i*26+j])); printf("  "); } printf("\n");  }     Encrypt_s(key);     return 0; } int letter_to_digit(char c)  //字母——数字 {     int i;    char alphabet[26]; for(int i=0;i<26;i++)alphabet[i]='a'+i;     for(i=0;i<26;i++)     {         if(tolower(c)==alphabet[i])         {             return (i);         }     }     return(-1); } char digit_to_letter(int n)//数字-——字母 {     char alphabet[26]; for(int i=0;i<26;i++)alphabet[i]='a'+i;     if(n<0 || n>25)     {         return (0);     }     return (alphabet[n]); } unsigned char *KeyGen_s()      //用于生成密码本 {     char KeyWords[106];     char ChoiceWords[26];     unsigned char *p;    static unsigned char KeyTab[26*3];//创建密码本     int i, j, k, l;     printf("\n请输入密钥字:\n");     gets(KeyWords);  strcat(KeyWords,"abcdefghijklmnopqrstuvwxyz");     k=0;     l=strlen(KeyWords);     ChoiceWords[k]=tolower(KeyWords[0]);     for(i=1;i<l;i++) //密钥字法后续删除重复字母     {         if(letter_to_digit(KeyWords[i])==-1)         {             continue;         }         ChoiceWords[++k]=tolower(KeyWords[i]);         for(j=0;j<k;j++)         {             if(ChoiceWords[j]==ChoiceWords[k])             {                 k--;                 break;             }         }     }     for(i=0;i<26;i++)     {         KeyTab[i]=(unsigned char)letter_to_digit(ChoiceWords[i]); //密码本前26 (密钥字法)     }     p=full_array1(25);  //生成随机全排列     for(i=0;i<26;i++)     {     KeyTab[26+i]=p[i];     //密码本27~52(抽牌法)     }     for(i=0;i<26;i++)     {      KeyTab[52+i]=(unsigned char)((11*i+3)%26); //密码本53~78    公式为11*i+3(mod 26)     }     return(KeyTab); } void Encrypt_s(unsigned char *key)     // 读取文件,输出密文 {     int i;     FILE *fp;     char filename[20], c;     start:         printf("\n请输入待加密文本文件名:\n");         scanf("%s", filename);         if((fp=fopen(filename,"rt"))==NULL)         {             printf("没有找到文件:%s\n",filename);             goto start;         }         printf("\n密文如下:\n");         i=0;         while((c=fgetc(fp))!=EOF)         {             if(letter_to_digit(c)==-1)             {                 putchar(c);                 continue;             }              isupper(c)?putchar(toupper(digit_to_letter(key[(int)((i%3)*26+letter_to_digit(c))]))):\ putchar(digit_to_letter(key[(int)(i%3)*26+letter_to_digit(c)]));             i++;             if(i>=26*3)i=0;         }         fclose(fp); } unsigned char *full_array1(int n) {     int i,j;     char filename[20];     FILE *fp;     static unsigned char d[256],P[256],temp;     start:         printf("\n 请输入随机数据采样文件名:\n");         scanf("%s",filename);         if( (fp=fopen(filename,"rb"))==NULL )         {            printf("没有找到文件:%s\n",filename);             goto start;         }     fread(d,n+1,1,fp);     fclose(fp);     for(i=0;i<=n;i++)     {         P[i] = i ; //形成自然排列     }     for(i=n;i>0;i--)     {         j=(d[i-1]+d[i])%i ;         temp = P[i] ;         P[i] = P[j];         P[j] = temp; //交换     }     return(P); }

题目二:

#include <stdio.h> #include <time.h> #include <stdlib.h> unsigned char *full_array2(int n); unsigned char *KeyGen_p(); void Encrypt_p(unsigned char *key); int main() {     unsigned char *key;     key=KeyGen_p(); for(int i=0;i<5;i++){ for(int j=0;j<16;j++){ printf("  %d",key[i*16+j])) } printf("\n");  }     Encrypt_p(key);     return 0; } unsigned char *KeyGen_p() {     unsigned char *p;     static unsigned char KeyTab[16*5];     int i, j;     for(i=0;i<5;i++)     {         p=full_array2(15);         for(j=0;j<16;j++)         {             KeyTab[16*i+j]=p[j];         }     }     return(KeyTab); } void Encrypt_p(unsigned char *key) {     int i, j;     FILE *fp;     char filename[26], c;     char d[16];     start:         printf("\n请输入待加密文本文件名:\n");         scanf("%s", filename);         if((fp=fopen(filename,"rt"))==NULL)         {             printf("没有找到文件:%s\n",filename);             goto start;         }         printf("\n密文如下:\n");         i=0;         while((c=fgetc(fp))!=EOF)         {             d[i%16]=c;             i++;             if(i%16!=0)             {                 continue;             }             for(j=0;j<16;j++)             {                 putchar(d[key[(int)(((i-1)/16)*16+j)]]);             }             if(i>=16*5)             {                 i=0;             }         }         if(i%16!=0)         {             for(j=i%16;j<16;j++)             {                 d[j]='*';             }             for(j=0;j<16;j++)             {                 putchar(d[key[(int)((i/16)*16+j)]]);             }         }         putchar('\n'); } unsigned char *full_array2(int n) {     int m, i, j, k, l=0, flag;     static unsigned char P[256];     start:  printf("\n请输入不小于%d的所用随机数个数:\n", n+1);         scanf("%d",&m);         if(m<=n)         {             printf("\n输入数%d比%d小,须重新输入!\n", m, n+1);                 goto start;         }         srand((unsigned)time(NULL));         for(i=0;i<m;i++)         {             P[l++]=(unsigned char)(rand()%(n+1));             for(j=0;j<l-1;j++)             {                 if(P[j]==P[l-1])                 {                     l--;                     break;                 }             }         }         k=l;         for(i=0;i<=n;i++)         {             flag=0;             for(j=0;j<k;j++)             {                 if(P[j]==i)                 {                     flag=l;                     break;                 }             }             if(!flag)             {                 P[l]=i;                 l++;             }         }         return (P); }

3.测试结果

密文:

c语言程序设计实验与案例答案_密码学应用

(1)替换密码

运行结果:

c语言程序设计实验与案例答案_密码学应用

检验:密码本如下

a

b

c

d

e

f

g

h

i

j

k

l

m

n

o

p

q

r

s

t

u

v

w

x

y

z

j

y

k

a

b

c

d

e

f

g

h

i

l

m

n

o

p

q

r

s

t

u

v

w

x

z

c

w

n

v

g

t

x

a

e

f

s

y

b

o

p

j

d

l

i

u

k

z

h

q

m

r

d

o

z

k

v

g

r

c

n

y

j

u

f

q

b

m

x

i

t

e

p

a

l

w

h

s

检验前六位:

明文

Q

i

s

a

s

y

密文

P

e

t

j

i

h

检验结果正确。

(2)移位密码

运行结果:

c语言程序设计实验与案例答案_密码学应用

检验:密码本如下

0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

0

6

7

8

3

10

1

11

4

9

13

12

14

2

5

15

3

2

0

8

14

9

11

5

10

1

6

15

7

12

4

13

6

14

8

7

2

12

0

1

5

13

3

4

15

9

10

11

0

4

5

8

11

14

15

6

9

3

1

10

2

12

7

13

7

12

1

4

13

9

0

14

3

8

6

10

2

5

11

15

检验前16位:

Q

i

s

a

  

s

y

m

m

e

t

r

i

c

Q

  

s

y

s

m

   

e

m

r

t

i

i

a

c

检验结果正确。

4.遇到问题

在实验过程中部分代码参考实验指导书,因此在实验过程中,发现实验指导书上存在的一些问题

(1)程序报错c语言程序设计实验与案例答案_密码学应用

程序在运行此行代码时报错,原因与长度有关。

解决方法:改进代码,如下。

char alphabet[i];

for(int i=0;i<26;i++)alphabet[i]=’a’+i;

(2)实验指导书关于题目一代码错误

c语言程序设计实验与案例答案_密码学应用

按照次代码,会将明文前26个用密钥字法加密;第二个26用抽牌法加密……。与要求周期3不符。

解决方法:修改代码,将i除26修改为i模3;

正在上传…重新上传取消

四、实验体会

本次是密码学的第一次实验,主要是两种基本古典密码设计与实现,在操作之中逐渐熟悉了他们的使用方法并了解了两种密码的差异。

    本次实验的函数对我相对困难,因此部分函数借鉴了实验指导书,在对实验指导书的学习过程中,我也发现了实验指导书上面存在一些问题,并通过自己的理解修改了函数,并得到了老师的肯定。

能发现问题,源自于我对题目的深刻理解,这次实验之前的预习必不可少,投入的时间终究会有回报。

五、思考题

思考题:“代替表”与“置换”的不动点、逆等是否一致?

不一致。

代替密码的实质是从明文空间通过一定的映射关系到密文空间,已经不再是原来的集合了。移位密码的实质是在明文空间内部,通过移动明文位置,使明文乱序,从而达到加密的目的。两者的不动点和逆只有在统一集合变换时才可能一样。

2024最新激活全家桶教程,稳定运行到2099年,请移步至置顶文章:https://sigusoft.com/99576.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。 文章由激活谷谷主-小谷整理,转载请注明出处:https://sigusoft.com/147618.html

(0)
上一篇 2024年 6月 30日 下午12:32
下一篇 2024年 6月 30日 下午12:39

相关推荐

关注微信