栅栏密码解密——Java实现

栅栏密码


实验目的:理解典型移位密码的加解密原理
实验原理:
栅栏密码属于古典密码中最经典的移项式密码,同之前讲到的凯撒密码等替 换式密码代表了密码学中最重要的两个概念(扩散和混淆)
我们以2栏栅栏密码为例来讲解它的加密和解密过程。
加密过程:
明文:THERE_IS_A_CIPHERK
两个一组,得到:(TH) (ER) (E_) (IS) (_A) (_C) (IP) (HE) (RK)
先每组中取出第一个字母:TEEI__IHR
再从每组中取出第二个字母:HR_SACPEK
连在一起得到密文:TEEI__IHRHR_SACPEK
解密过程:
而解密的时候,我们先把密文从中间分开,变为两行:
TEEI__IHR
HR_SACPEK
再按上下上下的顺序组合起来:
THERE_IS_A_CIPHERK
那么如何将2栏密码扩展到多栏呢?在之前的明文中,CIPHER这个单词之后加了一个下划线,目的就是为了让明文字符串的长度是2的倍数,栅栏密码的分栏的一个前提就是分的栏数需是明文长度的因数,这样才会使得分出来的每个栏长度都一样。
对于多栏,我们还是用上面的例子来讲解。
上面的明文字符串(THERE-IS_A_CIPHER-)的长度是18=233 ,所以我们可以把它分为2,3,4,6,9栏,这里我们以6栏为例。
以每个元素相隔6个字符分割出栅栏。
第一栏:TII
第二栏:HSP
第三栏:E_H
第四栏:RAE
第五栏:E_R
第六栏:-C-
连接在一起得到密文:TIIHSPE_HRAEE_R-C-

实验要求:
1.解密文本:_pry_iosncta_aguccropi_osieyghsrr_e-
2.将所有可能分的栏,均恢复出相应的明文


import java.util.ArrayList;

//栅栏密码
public class Demo {

	public static void main(String[] args) {
	
		String str = "_pry_iosncta_aguccropi_osieyghsrr_e-";
		
		//通过字符长度的因数判断可设置的分栏数n
		ArrayList<Integer> n = new ArrayList<>();
		for(int x=2;x<str.length();x++) {
			if(str.length()%x == 0) {
				n.add(x);
			}
		}
		
		//输出所有分栏可能
		for(int i:n) {
			System.out.println("可分为"+i+"栏:");
			//设置二维字符数组分别存储各分栏字符
			char[][] num = new char[i][str.length()/i];
			//遍历打印i栏
			for(int j=0;j<i;j++) {	
				//cut为各分栏字符串
				String cut = str.substring(j*str.length()/i, j*str.length()/i+str.length()/i);
				//num数组每行存储各分栏字符串cut
				num[j] = cut.toCharArray();
				
				System.out.println(cut);		
			};
			
			//解密过程实现
			//设置end集合存储存储Character对象取得解密结果
			ArrayList<Character> end = new ArrayList<>();
			//通过二维数组存储每个字符,使各字符可定位
			for(int k = 0; k < num.length; k++) {
				
	            for(int j = 0; j <num[k].length; j++) {
	                
	                for(int m = 0; m < num.length; m++) {
	                	 end.add(num[m][j]);
	                }
	            }
			}
			//输出结果
			System.out.println("--------------------");
			System.out.println(i+"分栏连接在一起得到密文为:");
			//遍历截取解密结果并输出
			for(int y=0;y<end.size()/i;y++) {
				//字符不换行衔接打印
				System.out.print(end.get(y));
			}
			System.out.println();
			System.out.println("--------------------");
		}
		
	}
}
栅栏密码是一种简单的加密方式,其原理是将明文按照一定长度分成若干个小段,然后将这些小段排列成一个矩阵,再按照一定顺序读取矩阵中的元素即可得到密文。解密时只需要将密文按照相同的顺序排列成矩阵,再按照顺序读取矩阵中的元素即可得到明文。 以下是 Java 实现栅栏密码的加密和解密的示例代码: ```java public class RailFenceCipher { // 加密 public static String encrypt(String plaintext, int rails) { int len = plaintext.length(); char[][] fence = new char[rails][len]; for (int i = 0; i < rails; i++) { for (int j = 0; j < len; j++) { fence[i][j] = '.'; } } int rail = 0, dir = 1; for (int i = 0; i < len; i++) { fence[rail][i] = plaintext.charAt(i); rail += dir; if (rail == 0 || rail == rails - 1) { dir = -dir; } } StringBuilder ciphertext = new StringBuilder(); for (int i = 0; i < rails; i++) { for (int j = 0; j < len; j++) { if (fence[i][j] != '.') { ciphertext.append(fence[i][j]); } } } return ciphertext.toString(); } // 解密 public static String decrypt(String ciphertext, int rails) { int len = ciphertext.length(); char[][] fence = new char[rails][len]; for (int i = 0; i < rails; i++) { for (int j = 0; j < len; j++) { fence[i][j] = '.'; } } int rail = 0, dir = 1; for (int i = 0; i < len; i++) { fence[rail][i] = '*'; rail += dir; if (rail == 0 || rail == rails - 1) { dir = -dir; } } int idx = 0; for (int i = 0; i < rails; i++) { for (int j = 0; j < len; j++) { if (fence[i][j] == '*' && idx < len) { fence[i][j] = ciphertext.charAt(idx++); } } } StringBuilder plaintext = new StringBuilder(); rail = 0; dir = 1; for (int i = 0; i < len; i++) { plaintext.append(fence[rail][i]); rail += dir; if (rail == 0 || rail == rails - 1) { dir = -dir; } } return plaintext.toString(); } public static void main(String[] args) { String plaintext = "HELLO WORLD"; int rails = 3; String ciphertext = encrypt(plaintext, rails); String decrypted = decrypt(ciphertext, rails); System.out.println("Plaintext: " + plaintext); System.out.println("Ciphertext: " + ciphertext); System.out.println("Decrypted: " + decrypted); } } ``` 输出结果: ``` Plaintext: HELLO WORLD Ciphertext: HORELWRLLDO Decrypted: HELLO WORLD ``` 在上面的示例代码中,encrypt() 方法实现栅栏密码的加密,decrypt() 方法实现栅栏密码解密,main() 方法演示了如何使用这两个方法加密解密字符串。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值