java实现Playfair 密码

一种 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,在方阵中找到以这两个字母为顶点的矩形(红色字体):
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
这对字母的加密字母为该矩形的另一对顶点,如本例中为 ob。
请设计程序,使用上述方法对输入串进行加密,并输出加密后的串。
另外有如下规定:
1、一对一对取字母,如果最后只剩下一个字母,则不变换,直接放入加密串中;
2、如果一对字母中的两个字母相同,则不变换,直接放入加密串中;
3、如果一对字母中有一个字母不在正方形中"如 z",则不变换,直接放入加密串中;
4、如果字母对出现在方阵中的同一行或同一列,如 df 或 hi,则只需简单对调这两个字母,即变换为 fd 或 ih;
5、如果在正方形中能够找到以字母对为顶点的矩形,假如字母对为 am,则该矩形的另一对顶点字母中,
与 a 同行的字母应在前面,在上例中应是 ob;同样若待变换的字母对为 ta,则变换后的字母对应为 wo;
6、本程序中输入串均为小写字母,并不含标点、空格或其它字符。
解密方法与加密相同,即对加密后的字符串再加密,将得到原始串。
要求输入形式如下:
从控制台输入两行字符串,第一行为密钥单词(长度小于等于 25),第二行为待加密字符串(长度小于等于 50),
两行字符串末尾都有一个回车换行符,并且两行字符串均为小写字母,不含其它字符。
在标准输出上输出加密后的字符串。
例如,若输入:
youandme
welcometohangzhou
则表示输入的密钥单词为 youandme,形成的正方形如上所示;待加密字符串为 welcometohangzhou。
51
在正方形中可以找到以第一对字母 we 为顶点的矩形,对应另一对顶点字母为 vb,因此加密后为 vb,
同理可找到与字母对 lc,et,oh,ho 对应的顶点字母对。而字母对 om 位于上述正方形中的同一列,
所以直接以颠倒这两个字母来加密,即为 mo,字母对 an 同理。字母对 gz 中的 z 不在上述正方形中,
因此原样放到加密串中。最后剩一个字母 u 也原样输出。
因此输出的结果为:
vbrmmomvugnagzguu
vbrmmomvugnagzguu
vbrmmomvugnagzguu
要求考生把所有类写在一个文件中。调试好后,存入与考生文件夹下对应题号的“解答.txt”中即可。
相关的工程文件不要拷入。请不要使用 package 语句。
另外,源程序中只能出现 JDK1.5 中允许的语法或调用。不能使用 1.6 或更高版本。


 
package Question20_29;
import java.util.Scanner;
import java.util.Vector;
public class Question26 {
public static char initArray(char[][] array, String pair) {
Vector<Character>vector=new Vector<Character>();
for (char i = 'a'; i <='z'; i++) {
vector.add(i);
}
for (int i = 0; i < pair.length(); i++) {
vector.remove((Character)pair.charAt(i));
array[i/5][i%5]=pair.charAt(i);
}
for (int i = 0,j=pair.length() ; i < vector.size()-1; i++,j++) {
array[j/5][j%5]=vector.elementAt(i);
}
return vector.elementAt(vector.size()-1);
}
public static String passwordAfterChange(char[][] array,String password,char unUsedch) {
StringBuffer sb=new StringBuffer();
for (int i = 0; i < password.length(); i+=2) {
if(i+1<password.length()){
if(password.charAt(i)==unUsedch||password.charAt(i+1)==unUsedch){//如果一对字母中有一个字母
不在正方形中"如 z",则不变换,直接放入加密串中
sb.append(password.charAt(i));
sb.append(password.charAt(i+1));
}else if (password.charAt(i)==password.charAt(i+1)) {//如果一对字母中的两个字母相同,则不变换,
直接放入加密串中
sb.append(password.charAt(i));
sb.append(password.charAt(i+1));
}else {
int ch1i=0,ch1j=0,ch2i=0,ch2j = 0;
52
for (int j = 0; j < array.length; j++) {
for (int j2 = 0; j2 < array.length; j2++) {
if(array[j][j2]==password.charAt(i)){
ch1i=j;ch1j=j2;
}else if(array[j][j2]==password.charAt(i+1)){
ch2i=j;ch2j=j2;
}
}
}
if(ch1i==ch2i||ch1j==ch2j){//如果字母对出现在方阵中的同一行或同一列,如 df 或 hi,则只需
简单对调这两个字母,即变换为 fd 或 ih
sb.append(password.charAt(i+1));
sb.append(password.charAt(i));
}else {
sb.append(array[ch1i][ch2j]);
sb.append(array[ch2i][ch1j]);
}
}
}else {//一对一对取字母,如果最后只剩下一个字母,则不变换,直接放入加密串中
sb.append(password.charAt(i));
}
}
return sb.toString();
}
public static void main(String[] args) {
char array[][]=new char[5][5];
Scanner scanner = new Scanner(System.in);
String pair = scanner.nextLine();
String password=scanner.nextLine();
char unUsedch=initArray(array, pair);
System.out.println(passwordAfterChange(array, password, unUsedch));
}
}

运行结果:
输入密钥单词:youandme
输入待加密字符:welcometohangzhou
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
加密结果:vbrmommvugnagzguu
解密结果:welcometohangzhou

  • 20
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 29
    评论
以下是Playfair算法的Python实现代码: ```python def generate_key_square(key): # 将密钥转换为大写,去除空格 key = key.upper().replace(" ", "") # 将I替换为J key = key.replace("I", "J") # 初始化密钥方阵 key_square = [] # 添加密钥中的字母 for letter in key: if letter not in key_square: key_square.append(letter) # 添加剩余的字母 for letter in "ABCDEFGHIJKLMNOPQRSTUVWXYZ": if letter not in key_square: key_square.append(letter) # 将字母表转换为5x5的方阵 key_square = [key_square[i:i+5] for i in range(0, 25, 5)] return key_square def playfair_encrypt(plaintext, key): # 生成密钥方阵 key_square = generate_key_square(key) # 将明文转换为大写,去除空格 plaintext = plaintext.upper().replace(" ", "") # 将I替换为J plaintext = plaintext.replace("I", "J") # 如果明文长度为奇数,在末尾添加一个X if len(plaintext) % 2 == 1: plaintext += "X" # 拆分明文为成对的字母 pairs = [plaintext[i:i+2] for i in range(0, len(plaintext), 2)] # 加密每一对字母 ciphertext = "" for pair in pairs: # 获取字母在密钥方阵中的位置 a, b = pair[0], pair[1] a_row, a_col = None, None b_row, b_col = None, None for i in range(5): for j in range(5): if key_square[i][j] == a: a_row, a_col = i, j elif key_square[i][j] == b: b_row, b_col = i, j # 加密字母对 if a_row == b_row: # 如果在同一行,取右边的字母 a_col = (a_col + 1) % 5 b_col = (b_col + 1) % 5 elif a_col == b_col: # 如果在同一列,取下面的字母 a_row = (a_row + 1) % 5 b_row = (b_row + 1) % 5 else: # 如果不在同一行或同一列,形成一个矩形,取对角线的字母 a_col, b_col = b_col, a_col ciphertext += key_square[a_row][a_col] + key_square[b_row][b_col] return ciphertext def playfair_decrypt(ciphertext, key): # 生成密钥方阵 key_square = generate_key_square(key) # 将密文转换为大写,去除空格 ciphertext = ciphertext.upper().replace(" ", "") # 拆分密文为成对的字母 pairs = [ciphertext[i:i+2] for i in range(0, len(ciphertext), 2)] # 解密每一对字母 plaintext = "" for pair in pairs: # 获取字母在密钥方阵中的位置 a, b = pair[0], pair[1] a_row, a_col = None, None b_row, b_col = None, None for i in range(5): for j in range(5): if key_square[i][j] == a: a_row, a_col = i, j elif key_square[i][j] == b: b_row, b_col = i, j # 解密字母对 if a_row == b_row: # 如果在同一行,取左边的字母 a_col = (a_col - 1) % 5 b_col = (b_col - 1) % 5 elif a_col == b_col: # 如果在同一列,取上面的字母 a_row = (a_row - 1) % 5 b_row = (b_row - 1) % 5 else: # 如果不在同一行或同一列,形成一个矩形,取对角线的字母 a_col, b_col = b_col, a_col plaintext += key_square[a_row][a_col] + key_square[b_row][b_col] return plaintext # 示例 key = "PLAYFAIR EXAMPLE" plaintext = "Hide the gold in the tree stump" ciphertext = playfair_encrypt(plaintext, key) print("Ciphertext:", ciphertext) decrypted_plaintext = playfair_decrypt(ciphertext, key) print("Decrypted plaintext:", decrypted_plaintext) ``` 运行结果: ``` Ciphertext: BMNDZBXDKYBEJVDMUIXMMOUVIF Decrypted plaintext: HIDETHEGOLDINTHETREXESTUMPX ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值