系列文章目录



前言

矩阵密码是一种常见的密码,将明文填入以秘钥长度为列数的矩阵当中,并按照秘钥大小按列输出字符串,从而实现加密。本次矩阵密码的实现大致分为处理秘钥、加密算法、解密算法三大部分。主要代码为对秘钥进行大小排序,得到sort[ ] 数组,利用sort[ ] 数组进行明文的输出和密文的输入;对矩阵空位置的处理,秘钥不定,明文不定,必然存在余数不为零的情况,通过计算得到空位置数量,对其进行特殊填充处理。

一、代码讲解

矩阵密码整体分为,处理秘钥、加密算法、解密算法三部分。其中加密算法又分为处理明文输入、判断矩阵行列个数、机密矩阵输出、sort[ ] 排序、密文输出。整体的设计思路为现将输入的秘钥转成int[ ] 类型,将输入的明文字符串转为String[ ] 类型,将秘钥长度设为列数,行数根据秘钥长度进行判断,使用双循环存储矩阵并输出,使用sort()函数对秘钥大小进行排序,确定输出列顺序,最后使用print()函数输出密文,此时加密完成。在print()函数当中将密文进行存储,同样获取行列个数,并使用sort()获取排列顺序,根据sort[ ]总存储的数据,将密文填充到解密矩阵里面,最后按行输出。具体过程。如下图所示。
在这里插入图片描述

1、处理秘钥

从键盘键入一串字符串,将其根据null进行分割成String[ ]类型,再利用循环转换成int[ ]类型,关键代码如下:

	  String str = sc.next().toString();
	  String[] arr = str.split("");
	  key[i] = Integer.parseInt(arr[i]);

2、加密算法

① 判断矩阵行列个数

      行:a=明文长度/秘钥长度
      列:b=秘钥长度

判断行的数量需要用到判断,如果名文书可以整除秘钥数也就是lenE/lenK,则行的数量就是整除的数,如果不能整除,需要增加一行存放余数。如下图所示。
在这里插入图片描述

② 加密矩阵输出

使用双循环,将明文串填充在加密矩阵当中,在k小于lenE的情况下,并输出,关键代码如下:

for(int i=0;i<a;i++) {
		for(int j=0;j<b;j++) {
				en[i][j] = encryStr[k++];
				System.out.print(en[i][j]);
		}
		System.out.print("\n");
	}

③ 秘钥大小排序数组

利用矩阵秘钥的特点,从1开始的连续整型数字,从1 判断在秘钥当中的位置,存入sort[ ]当中,下标从0开始。例如秘钥为546213,则sort[ ]当中的数据为435102。如下图所示。
在这里插入图片描述

       for(int i=1;i<lenK+1;i++) {       //双循环判断从小到大数字位置
			for(int j=0;j<lenK;j++) {
				if(i==key[j]) {
					sort[i-1]=j;
				}
			}
		}

3、解密算法

① 使用“.”填充空余。按列向矩阵中填充数据的时候,因为密文不是秘钥的整数倍,所有会出现矩阵最后一行为空的现象。在此使用了将应该为空的地方通过计算算出来,然后填充“.”符号进行区分,通过判断是否是“.”来判断是否填入数据。具体过程如图所示。计算的过程是通过lenD%lenK的数据,说明剩余的个数,用列数减去余数,就是最后空的数量,因为为空只可能是最后一行的情况,所以使用下列代码:

for(int i=len;i>0;i--) {
		de[a-1][b-i]=".";
	}

例如密文为decyptStr={a,b,c,d,e,f,g,h,i,j},秘钥为key={2,1,4,3},第一步先通过计算得到len=2,第二步再向矩阵的最后一行的最后两个填充“.”符号,第三步利用循环不等于特定符号的填充明文。如下图所示。
在这里插入图片描述

二、完整代码

import java.util.Scanner;

public class juzhen {

	/**
	 * 加密
	 * @param lenK
	 * @param key
	 */
	public static void encrypt(int lenK,int[] key) {
		
		//明文输入
		Scanner sc = new Scanner(System.in);
		System.out.print("please input enString:");
		String str = sc.next().toString();
		String[] encryStr = str.split("");
		
		//判断行列数
		int lenE = encryStr.length;
		int a = 0;       //行
		int b = lenK;    //列
		if(lenE%lenK==0) {
			a = lenE/lenK;
		}else {
			a = lenE/lenK+1;
		}
		
		/*矩阵填充-输出*/
		String[][] en = new String[a][b];   //明文加密矩阵
		int k = 0;
		System.out.print("矩阵输出:\n");
		for(int i=0;i<lenK;i++) {
			System.out.print(key[i]);
		}
		System.out.print("\n");
		for(int i=0;i<lenK;i++) {
			System.out.print("-");
		}
		System.out.print("\n");
		for(int i=0;i<a;i++) {
			for(int j=0;j<b;j++) {
				if(k<lenE) {
					en[i][j] = encryStr[k++];
					System.out.print(en[i][j]);
				}else {
					break;
				}	
			}
			System.out.print("\n");
		}

		
		String[] decryptStr = new String[lenE];
		int[] sort = new int[lenK];   //秘钥排序数组
		sort = sort(key,lenK);       
		print(a,b,sort,decryptStr,en);
		decrypt(lenK,decryptStr,sort);   //解密
	}
	
	/**
	 * 排序
	 * @param key
	 * @param lenK
	 * @return
	 */
	public static int[] sort(int[] key,int lenK) {
		int[] sort = new int[lenK];
		for(int i=1;i<lenK+1;i++) {       //双循环判断从小到大数字位置
			for(int j=0;j<lenK;j++) {
				if(i==key[j]) {
					sort[i-1]=j;
				}
			}
		}
		return sort;
	}
	
	/**
	 * 输出        按列非空输出
	 * @param a
	 * @param b
	 * @param sort
	 * @param en
	 */
	public static void print(int a,int b,int[] sort,String[] decryptStr,String[][] en) {
		int k=0;
		System.out.print("密文:");
		for(int i=0;i<b;i++) {
			for(int j=0;j<a;j++) {
				if(en[j][sort[i]]==null) {
					continue;
				}else {
					System.out.print(en[j][sort[i]]);
					decryptStr[k++]=en[j][sort[i]];       //存到密文数组
				}
			}
		}
	}
	
	/**
	 * 解密
	 * @param lenK
	 * @param decryptStr
	 * @param sort
	 */
	public static void decrypt(int lenK,String[] decryptStr,int[] sort) {
		int lenD = decryptStr.length;
		int a = 0;       //行
		int b = lenK;    //列
		if(lenD%lenK==0) {
			a = lenD/lenK;
		}else {
			a = lenD/lenK+1;
		}
		
		int len = lenD%lenK;  //判断余数
		if(len!=0) {
			len = b-len;
		}
		
		//空的地方填充
		String[][] de = new String[a][b];
		for(int i=len;i>0;i--) {
			de[a-1][b-i]=".";
		}
		
		//密文矩阵存储
		int k=0;
		for(int i=0;i<b;i++) {
			for(int j=0;j<a;j++) {
				if(de[j][sort[i]]==".") {    //存二维表
					continue;
				}else {
					de[j][sort[i]] = decryptStr[k++];
				}
			}
		}
		
		//按行非空输出
		System.out.print("\n明文:");     //输出
		for(int i=0;i<a;i++) {
			for(int j=0;j<b;j++) {
				if(de[i][j]!=".") {
					System.out.print(de[i][j]);
				}
			}
		}
	}
	
	
	public static void Go() {

	  System.out.print("please input key:");
	  Scanner sc = new Scanner(System.in);
	  /*输入字符串->整形数组*/
	  String str = sc.next().toString();
	  String[] arr = str.split("");
	  int[] key = new int[arr.length];     //秘钥
	  int lenK = arr.length;        //秘钥长度
	  for(int i = 0; i<key.length;i++) {
		  key[i] = Integer.parseInt(arr[i]);
	  }
	  
	  encrypt(lenK,key);
	}
}

三、结果演示

  • 实验结果1
    在这里插入图片描述
  • 实验结果2
    在这里插入图片描述

总结

以上就是今天要讲的内容,本文仅仅简单介绍了密码学当中的古典密码之一,矩阵密码。
这是小编在学习中,发现网上对于矩阵加密的java实现并没有非常多的资料,于是编写了一套代码,希望可以帮助到大家!如果还需要其他的加密算法,欢迎评论区留言或者私信~
道行不深,如果有发现问题,希望可以及时指出,谢谢啦!

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐