hill2

四、实验原理:
破译关键是求得加密矩阵的逆——解密矩阵。
分析出两个线性无关的明文向量与相应的密文向量,即可利用可逆矩阵求解矩阵方程计算出解密矩阵。即:

在这里插入图片描述

五、实验目的:
1、熟悉密码算法的基本破译方法;
2、理解密码算法破译中基于数学的分析方法的基本思路。
六、实验内容:
实现2阶Hill密码在已知明文攻击场景中,基于向量线性无关的破译。
七、实验器材(设备、元器件):
学生每人一台PC,安装Windows 7操作系统及VC++/Python开发环境。
八、实验步骤:
1.密钥生成
(1)
Rand()函数生成条件为模26的二阶矩阵,并且该矩阵的行列值与26互素
在这里插入图片描述

  1. 加密
    (1)计算明文的个数若为奇数则把flag置为1进行填充。
    将明文字母依次按每两个字母一组查出其表值,得到一组二维向量;通过加密矩阵得到而。
    查向量 i 的字母表值,即得到密文
    在这里插入图片描述

  2. 解密
    (1)利用加密矩阵的逆矩阵,由密文得到明文
    在这里插入图片描述

  3. 已知明文攻击原理
    (1)只要分析出两个明文向量(线性无关)与相应的密文向量
    若有

在这里插入图片描述

九、实验数据及结果分析:
1.实验参考代码:
加密:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX 60


int gcd(int a,int b){
	return b==0?a:gcd(b,a%b);
}

int main(){   
int p,q,dt;
int flag; 
char C[MAX] = {0};
char P[MAX] = {0};
int len;
int T2[MAX] = {0};
int T1[MAX] ={0};
int Temp1[2] = {0}, Temp2[2] = {0};
int i,j;
int key[2][2] = { {0,0},{0,0} };

printf("======= Hill密码加密 =======\n\n");
printf("生成的随机加密矩阵:\n");


do{
	key[0][0]=rand()%26;
    key[0][1]=rand()%26;
    key[1][0]=rand()%26;
    key[1][1]=rand()%26;
	dt = -1;
    for(p=1; dt < 0; p++)
    {
        dt = ((key[0][0] * key[1][1] - key[0][1] * key[1][0]) + 26 * p)%26; //行列式的值 
    }
}while(gcd(dt,26)!=1); 

for(p=0;p<2;p++){
        for(q=0;q<2;q++){
            printf("%d ",key[p][q]);} 
        printf("\n"); } 

printf("请输入明文:\n");
scanf("%s", P);
len = strlen(P);
// 当长度为奇数时补齐一位
        if(len % 2 == 1)
        {
            P[len] = P[len-1];
            len = strlen(P);
            flag=1;
        }
   
	
for(i=0; i<len; i++)
        {
            if(P[i] >= 'A' && P[i] <= 'Z')
            {
                P[i] = P[i] + 32;
            }

            T1[i] = P[i] - 'a';
        }

for(i=0; i<len; i+=2)
        {   
           
            Temp1[0] = T1[i];
            Temp1[1] = T1[i + 1];

            // Temp2存储密文int值
            Temp2[0] = (Temp1[0] * key[0][0] + Temp1[1] * key[1][0]) % 26;
            Temp2[1] = (Temp1[0] * key[0][1] + Temp1[1] * key[1][1]) % 26;

            T2[i] = Temp2[0];
            T2[i + 1] = Temp2[1];
            //printf("密文是%c%c",T2[i],T2[i+1]);
        }
if(flag == 1)
        {
            len = len - 1;
        }
   
for(i=0; i<4; i++)

        {
            C[i] = T2[i] + 'a';
            printf("%c", C[i]);
        }
        printf("\n");
  
  
  
  
    }

解密:

#include<stdio.h>
#include<string.h>
#include <stdlib.h>
#define MAX 60
int main(){
	char P[MAX] = {0};
char C[MAX] = {0};
int i,j;
int len;
int key[2][2] = { {0,0},{0,0} };
int flag;
int T2[MAX] = {0};
int T1[MAX] ={0};
int K2[2][2] = { {0,0},{0,0} };
int Temp1[2] = {0}, Temp2[2] = {0};
int temp,temp1;
    

printf("======= Hill 密码解密 =======\n\n");
    printf("请输入秘钥的值:\n");
    for(i=0; i<2; i++)
    {
        for(j=0; j<2; j++)
        {
            scanf("%d", &key[i][j]);
        }
    }
 printf("请输入密文:");
        scanf("%s", C);

        len = strlen(C);

        // 当长度为奇数时补齐一位
        if(len % 2 == 1)
        {
            C[len] = C[len-1];
            len = strlen(C);
            flag = 1;
        }
        
  for(i=0; i<len; i++)
        {
            if(C[i] >= 'A' && C[i] <= 'Z')
            {
                C[i] = C[i] + 32;
            }

            T2[i] = C[i] - 'a';
        }
        
temp = -1;
        for(i=1; temp < 0; i++)
        {
            temp = (key[0][0] * key[1][1] - key[0][1] * key[1][0]) + 26 * i;
        }

        i = 1;
        while(1)
        {
            if((temp * i) % 26 == 1)
            {
                temp1 = i;
                break;
            }
            else
            {
                i++;
            }
        }

        K2[0][0] = key[1][1] * temp1;
        K2[0][1] = (((-1 * key[0][1]) + 26) * temp1) % 26;
        K2[1][0] = (((-1 * key[1][0]) + 26) * temp1) % 26;
        K2[1][1] = key[0][0] * temp1;

//      printf(" %d %d   %d %d %d %d\n",temp, temp1, K2[0][0], K2[0][1], K2[1][0], K2[1][1]);
//      system("pause");
//      printf(" %d %d   %d %d %d %d\n",temp, temp1, K2[0][0]%26, K2[0][1]%26, K2[1][0]%26, K2[1][1]%26);
//      system("pause");



        
   for(i=0; i<len; i+=2)
        {
            Temp2[0] = T2[i];
            Temp2[1] = T2[i + 1];

            // Temp1存储明文int值
            Temp1[0] = (Temp2[0] * K2[0][0] + Temp2[1] * K2[1][0]) % 26;
            Temp1[1] = (Temp2[0] * K2[0][1] + Temp2[1] * K2[1][1]) % 26;

            T1[i] = Temp1[0];
            T1[i + 1] = Temp1[1];
        }

        if(flag == 1)
        {
            len = len - 1;
        }

        printf("解密结果为:\n");
        for(i=0; i<len; i++)
        {
            P[i] = T1[i] + 'a';
            printf("%c ", P[i]);
        }
        printf("\n");
     
        
        
}

攻击:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
	FILE *fp;
	int knownedc[2][2]={21,18,3,19},knowneda[2][2]={20,3,1,15},invcip[2][2]={0},invA[2][2]={0};
	int tran1[10000]={0},mes[10000]={0};
	int T1[2]={0},msg[2]={0};
	int i,j,detcip,invdetcip,len,flag;
    char c[10000]={'\0'}; //密文
	char pla[10000]={'\0'}; //明文
    detcip = -1;
    for(i=1; detcip < 0; i++){
            detcip = ((knownedc[0][0] * knownedc[1][1] - knownedc[0][1] * knownedc[1][0]) + 26 * i)%26;//令行列式为正数 
        }
    i = 1;
        while(1){
            if((detcip * i) % 26 == 1){
                invdetcip = i;
                break;
            }
            else
                i++;
        }
      invcip[0][0]=(knownedc[1][1]*invdetcip)%26;
      invcip[0][1]=(((-1 * knownedc[0][1]) + 26) * invdetcip) % 26;
      invcip[1][0]=(((-1 * knownedc[1][0]) + 26) * invdetcip) % 26;
      invcip[1][1]=(knownedc[0][0]*invdetcip)%26;

	  //加密矩阵A在模26下的逆矩阵
	  invA[0][0]=(knowneda[0][0]*invcip[0][0]+knowneda[0][1]*invcip[1][0])%26;
	  invA[0][1]=(knowneda[0][0]*invcip[0][1]+knowneda[0][1]*invcip[1][1])%26;
	  invA[1][0]=(knowneda[1][0]*invcip[0][0]+knowneda[1][1]*invcip[1][0])%26;
	  invA[1][1]=(knowneda[1][0]*invcip[0][1]+knowneda[1][1]*invcip[1][1])%26;
    //输出A逆矩阵 
	 printf("The Inverse of the encryption matrix :\n");
     for(i=0;i<2;i++){
        for(j=0;j<2;j++){
            printf("%d ",invA[i][j]); 
        } 
        printf("\n"); 
    }
      //打开需要解密的密文 
     if((fp=fopen("c.txt","r"))==NULL){
        printf("Open the file failure...\n");
        exit(0);
     } 
      i=0;
      while(!feof(fp)){
       c[i]=fgetc(fp);
	   i++;
	   }   
  	   len=strlen(c)-1;   //len是密文的长度
      // 当长度为奇数时补齐一位
       if(len % 2 == 1){
            c[len] = 'a';
            len = len+1;
            flag = 1;
      }
      for(i=0; i<len; i++){
            if(c[i] >= 'A' && c[i] <= 'Z') {//将大写转化为小写 
                c[i] = c[i] + 32;
            }
            tran1[i] = c[i] - 'z';    //构建对应表,即a-z对应表值0-25 
        }
      
        for(i=0; i<len; i+=2){
        	//储存字母对应表值,便于计算 
            T1[0] = tran1[i];          
            T1[1] = tran1[i + 1];
            // msg存储解密后明文int值
            msg[0] = (T1[0] * invA[0][0] + T1[1] * invA[0][1]) % 26;
            msg[1] = (T1[0] * invA[1][0] + T1[1] * invA[1][1]) % 26;
            //计算结束,将值赋给mes[],便于输出,mes的功能相当于计算前的tran1 
            mes[i] = msg[0];
            mes[i + 1] = msg[1];
        }
     
	  //对输入密文长度的判断,如是原密文为奇数则去除补位 
	  if(flag == 1)
            len = len - 1;
       printf("cracked plain text :\n");
        for(i=0; i<len; i++){
            pla[i] = mes[i] + 'z';   //根据对应表返回各表值对应的字母 
            printf("%c", pla[i]);
        }
        printf("\n");	
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值