Hill密码的加密与解密

Hill密码原理

首先随机生成或选取一个密钥矩阵(该矩阵必须是可逆的),过程如下图所示

在这里插入图片描述
在这里插入图片描述
  在加密过程中,先将明文分为三个字母一组,不足的用“X”代替,然后将其转化成数字,如0==‘A’,得到每个字母所对应的数字,再与密钥矩阵相乘,得到的数字转成字母,如’B’==1,进行拼接,即得到密文字符串,最后进行输出。
  在解密过程中,先求出密钥的逆矩阵,本文直接给出逆矩阵,需要注意的是逆矩阵的元素不可以为负数,若存在负数,则将所有元素+26的若干倍,再mod26,得到全为正整数的逆矩阵。将得到的密文字母转成数字(三个一组),与逆矩阵相乘,将所得的数字转成字母,即得到明文字符串,最后进行输出。

代码如下:

package gdut.com.information;

import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Hill {
	private static int[][] key = {{1,2,3},{1,1,2},{0,1,2}};		//密钥矩阵
	private static int[][] fkey = {{0,1,25},{2,24,25},{25,1,1}};	//密钥逆矩阵
	private static Map<Character,Integer> map1 = new HashMap<>();
	private static Map<Integer,Character> map2 = new HashMap<>();
	private static Scanner cin = new Scanner(System.in);
	public static void main(String[] args) {
		System.out.println("明文先按三个字母一组分组,不足三个是用X代替");
		System.out.println();
		System.out.println("==========加密过程==========");
		System.out.println("密钥矩阵如下:");
		showMartrix(key);
		matches();
		System.out.println("请输入明文:" );
		String s1 = cin.nextLine();
		String format1 = format(s1);
		encode(format1);
		System.out.println("==========解密过程==========");
		System.out.println("密钥逆矩阵如下:");
		showMartrix(fkey);
		int len = format1.length();
		decode(len);
	}
	

	/**
	 * 将字母与数字进行一一对应
	 */
	private static void matches() {
		for (int i = 0; i < 26; i++) {
			map1.put((char) (i+65), i);
		}
		for (int i = 0; i < 26; i++) {
			map2.put(i,(char) (i+65));
		}
		
	}

	/**
	 * 展示矩阵
	 * 
	 */
	private static void showMartrix(int[][] key2) {
		for (int i = 0; i < key2.length; i++) {
			for (int j = 0; j < key2[0].length; j++) {
				System.out.print(key2[i][j]+"     ");
			}
			System.out.println();
		}
		
	}
	
	/**
	 * 将小写字母转换成大写字母
	 */
	private static String format(String str) {
		String regEx="[^(A-Za-z)]";  //正则表达式
		Pattern p = Pattern.compile(regEx);   
		Matcher getStr = p.matcher(str);
		str = getStr.replaceAll("").trim();
		str = str.toUpperCase();
		return str;
	}
	
	/**
	 * 加密
	 */
	private static void encode(String str) {
		int len = str.length()/3;
		if(str.length()%3!=0) {
			len++;
		}
		String[] sb = new String[len];
		for (int i = 0; i < sb.length; i++) {
			sb[i]="";
		}
		int num = 0;
		int length = str.length();
		//将明文按照按照三个字母进行分组
		for (int i = 0; i < sb.length; i++) {
			for (int j = i*3; j < length; j++) {	//第i轮,应从下标i*3开始
				char c = str.charAt(j);
				sb[i] += c;
				num++;
				if(num%3 == 0) {
					num=0;
					break;
				}
			}
			//当不足三个字母时补X
			while(num!=0 && num<3) {
				sb[i] += "X";
				num++;
			}
		}
		System.out.print("密文为:");
		for (int i = 0; i < sb.length; i++) {
			int[] a = new int[3];
			for (int j = 0; j < sb[i].length(); j++) {
				a[j] = map1.get(sb[i].charAt(j));
			}
			int[] b = new int[3];
			for (int j = 0; j < a.length; j++) {
				b[j] = (key[j][0]*a[0]+key[j][1]*a[1]+key[j][2]*a[2])%26;
				System.out.print(map2.get(b[j]));
			}
		}
		System.out.println();
	}
	
	/**
	 * 解密
	 */
	private static void decode(int length) {
		StringBuffer sb = new StringBuffer();
		System.out.println("请输入密文:");
		String s2 = cin.nextLine();
		String format2 = format(s2);
		int len = format2.length();
		if(len%3 != 0) {
			System.out.println("密文数量必须为3的倍数,请重新输入");
			decode(length);
		}
		int i = 0;
		System.out.print("明文为:");
		while (i < len) {
			int[] a = new int[3];
			for (int j = 0; j < a.length; j++) {
				a[j] = map1.get(format2.charAt(i));
				i++;
			}
			int[] b = new int[3];
			for (int j = 0; j < a.length; j++) {
				b[j] = (fkey[j][0]*a[0]+fkey[j][1]*a[1]+fkey[j][2]*a[2])%26;
				sb.append(map2.get(b[j]));
			}
		}
		//把补充的字母"X"去掉
		String substring = sb.toString().substring(0, length);
		System.out.println(substring);
	}
}

ps: 如有不足,期待您的指点,谢谢!

  • 9
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值