密码学--矩阵加密_java实现(附带详细讲解)
矩阵密码是一种常见的密码,将明文填入以秘钥长度为列数的矩阵当中,并按照秘钥大小按列输出字符串,从而实现加密。本次矩阵密码的实现大致分为处理秘钥、加密算法、解密算法三大部分。主要代码为对秘钥进行大小排序,得到sort[ ] 数组,利用sort[ ] 数组进行明文的输出和密文的输入;对矩阵空位置的处理,秘钥不定,明文不定,必然存在余数不为零的情况,通过计算得到空位置数量,对其进行特殊填充处理。以上就是
系列文章目录
前言
矩阵密码是一种常见的密码,将明文填入以秘钥长度为列数的矩阵当中,并按照秘钥大小按列输出字符串,从而实现加密。本次矩阵密码的实现大致分为处理秘钥、加密算法、解密算法三大部分。主要代码为对秘钥进行大小排序,得到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实现并没有非常多的资料,于是编写了一套代码,希望可以帮助到大家!如果还需要其他的加密算法,欢迎评论区留言或者私信~
道行不深,如果有发现问题,希望可以及时指出,谢谢啦!
更多推荐



所有评论(0)