加密与解密_Playfair密码变种加密方法-解题思路及过程

来源:互联网 发布:java split函数 编辑:程序博客网 时间:2024/06/01 23:12

一.题目描述:

一种Playfair密码变种加密方法如下:首先选择一个密钥单词(称为pair)(字母不重复,且都为小写字母),然后与字母表中其他字母一起填入至一个5x5的方阵中,填入方法如下:

1.首先按行填入密钥串。

2.紧接其后,按字母序按行填入不在密钥串中的字母。

3.由于方阵中只有25个位置,最后剩下的那个字母则不需变换。

如果密钥为youandme,则该方阵如下:

y o u a n

d m e b c

f g h i j

k l p q r

s t v w x

在加密一对字母时,如am,在方阵中找到以这两个字母为顶点的矩形(红色字体):

o u a n

m e b c

f g h i j

k l p q r

s t v w x

这对字母的加密字母为该矩形的另一对顶点,如本例中为ob。

请设计程序,使用上述方法对输入串进行加密,并输出加密后的串。

另外有如下规定:

1、一对一对取字母,如果最后只剩下一个字母,则不变换,直接放入加密串中;

2、如果一对字母中的两个字母相同,则不变换,直接放入加密串中;

3、如果一对字母中有一个字母不在正方形中,则不变换,直接放入加密串中;

4、如果字母对出现在方阵中的同一行或同一列,如df或hi,则只需简单对调这两个字母,即变换为fd或ih;

5、如果在正方形中能够找到以字母对为顶点的矩形,假如字母对为am,则该矩形的另一对顶点字母中,与a同行的字母应在前面,在上例中应是ob;同样若待变换的字母对为ta,则变换后的字母对应为wo;

6、本程序中输入串均为小写字母,并不含标点、空格或其它字符。

解密方法与加密相同,即对加密后的字符串再加密,将得到原始串。

要求输入形式如下:

从控制台输入两行字符串,第一行为密钥单词(长度小于等于25),第二行为待加密字符串(长度小于等于50),两行字符串末尾都有一个回车换行符,并且两行字符串均为小写字母,不含其它字符。

在标准输出上输出加密后的字符串。

例如,若输入:

youandme

welcometohangzhou

则表示输入的密钥单词为youandme,形成的正方形如上所示;待加密字符串为welcometohangzhou。在正方形中可以找到以第一对字母we为顶点的矩形,对应另一对顶点字母为vb,因此加密后为vb,同理可找到与字母对lc,et,oh,ho对应的顶点字母对。而字母对om位于上述正方形中的同一列,所以直接以颠倒这两个字母来加密,即为mo,字母对an同理。字母对gz中的z不在上述正方形中,因此原样放到加密串中。最后剩一个字母u也原样输出。

因此输出的结果为:

vbrmmomvugnagzguu


二.解题思路:

这条题目我们完全可以根据上述的规定编写出我们所预想的程序。我的想法是:可以先设计一个线性列表,将26个字母一起放入其中,然后定义一个5x5的矩阵,将密钥按顺序放入其中(同时将放入矩阵中的字母从线性表中去除),等到将密钥全部放入矩阵中之后,再按照顺序将线性表中的其他字母一一放入矩阵中,这样就形成了一个密钥矩阵。

然后按照上述规定对其进行一一限制,这里说下加入字母对是为定点的矩形,那么很简单,只要将两个字母的所在的列的值交换下即可。


三.Java代码如下:

import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;public class Test {static String pair = "youandme";//密钥static List<Character> list = new ArrayList<Character>();//线性表static char[][] getMatrix(String pair) {//获取密钥矩阵int length = 0;char[][] matrix = new char[5][5];for (char i = 'a'; i <= 'z'; i++) {list.add(i);//将26个字母放入线性表}for (int i = 0; i < 5; i++) {for (int j = 0; j < 5; j++) {if (length < pair.length()) {char t = pair.charAt(length++);matrix[i][j] = t;//将密钥字母一个个放入矩阵中list.remove((Character) t);//将放入矩阵中的字母从线性表中移除} else {matrix[i][j] = list.remove(0);//将线性表中的字母填充进矩阵中,然后移除该字母}}}return matrix;}static String encoding(String s) {String result = "";char[][] matrix = getMatrix(pair);Map<String, Integer> map = new HashMap<String, Integer>();//获取字母对的x,y轴的坐标for (int k = 0; k < s.length(); k++) {char t1 = s.charAt(k++);char t2;if (s.length() % 2 != 0 && k == s.length()) {//最后如果只有一个人字母则直接加入结果result += t1;break;} elset2 = s.charAt(k);if (list.contains(t1) || list.contains(t2)) {//如果字母对中任一字母在线性表中,//即代表不再矩阵中,则将字母对直接加入结果result += t1 + "" + t2;continue;}if (t1 == t2) {result += t1 + "" + t2;//如果字母对相同,则直接加入结果} else {for (int i = 0; i < 5; i++) {for (int j = 0; j < 5; j++) {if (matrix[i][j] == t1) {map.put("t1_x", i);map.put("t1_y", j);}if (matrix[i][j] == t2) {map.put("t2_x", i);map.put("t2_y", j);}}}if ((Integer) map.get("t1_x") == (Integer) map.get("t2_x")//如果字母对在同一个行或列则交换字母后加入结果|| (Integer) map.get("t1_y") == (Integer) map.get("t2_y")) {result += t2 + "" + t1;} else {//如果字母对成一个矩形,调换两个字母的y轴坐标后获取在矩阵中的值加入结果result += matrix[(Integer) map.get("t1_x")][(Integer) map.get("t2_y")]+ ""+ matrix[(Integer) map.get("t2_x")][(Integer) map.get("t1_y")];}}}return result;}public static void main(String[] args) {String s = "welcometohangzhou";String result = encoding(s);System.out.println(result);}}

结果如下:


题目完成,以上为个人思路,仅供参考,有什么不到位的地方欢迎批评指正,谢谢......

0 0