①维吉尼亚(Vigenere)密码算法简介
维吉尼亚密码是使用一系列凯撒密码组成密码字母表的加密算法,属于多表密码的一种简单形式。它的算法思想如下:明文的每个字母使用不同k的凯撒加密。我们可以构造一个维吉尼亚密码表的矩阵,矩阵实例如图1.1所示,最左边为密钥所包含的字母,最上面为明文所包含的字符,加密过程很简单:给定密钥字母x和明文字母y,利用维吉尼亚加密之后密文字母为位于x行和y列的字母
图 1.1
例如给出明文为COMPUTER,密钥为ACM,使用维吉尼亚算法进行加密,得到的密文过程如图1.2所示
图 1.2
这些密文字母在矩阵中的表示如图1.3所示
维吉尼亚加密法其实是针对明文中的每个字母单独提供一个密钥字母作为偏移量进行替换,可用公式表示为Ci=Ki+Pi,在实际代码编写过程中可用0~25代表字母A~Z来进行计算。以上就是维吉尼亚加密算法的思想。同样可以将字母推广到数字和符号中。
②维吉尼亚(Vigenere)算法代码实现
(1)加密算法代码实现
public static String Encryption(String plaintext, String vigekey) {
// 声明一个空字符串用来存放加密后的密文
String cipher = "";
// for循环对字符串中每个字符进行加密操作
for (int i = 0; i < plaintext.length(); i++) {
// 字符变量用于存放依次取出的字符串中的字符
char p = plaintext.charAt(i);
// 取出明文中每个字符对应的密钥
char v = vigekey.charAt(i % vigekey.length());
if (p >= 'A' && p <= 'Z') {// 明文中的大写字母的转换
if (v >= 'A' && v <= 'Z') {// 密钥是大写字母
p = (char) (((p - 'A') + (v - 'A')) % 26 + 'A');
} else if (v >= 'a' && v <= 'z') {// 密钥是小写字母
p = (char) (((p - 'A') + (v - 'a')) % 26 + 'A');
} else if (v >= '0' && v <= '9') {// 密钥是数字
p = (char) (((p - 'A') + (v - '0')) % 26 + 'A');
}
} else if (p >= 'a' && p <= 'z') {// 明文是小写字母的转换
if (v >= 'A' && v <= 'Z') {// 密钥是大写字母
p = (char) (((p - 'a') + (v - 'A')) % 26 + 'a');
} else if (v >= 'a' && v <= 'z') {// 密钥是小写字母
p = (char) (((p - 'a') + (v - 'a')) % 26 + 'a');
} else if (v >= '0' && v <= '9') {// 密钥是数字
p = (char) (((p - 'a') + (v - '0')) % 26 + 'a');
}
} else if (p >= '0' && p <= '9') {// 明文是数字的转换
if (v >= 'A' && v <= 'Z') {// 密钥是大写字母
p = (char) (((p - '0') + (v - 'A')) % 10 + '0');
} else if (v >= 'a' && v <= 'z') {// 密钥是小写字母
p = (char) (((p - '0') + (v - 'a')) % 10 + '0');
} else if (v >= '0' && v <= '9') {// 密钥是数字
p = (char) (((p - '0') + (v - '0')) % 10 + '0');
}
}
cipher += p;
}
return cipher;
}
(2)解密算法代码实现
public static String Decryption(String criphertext, String vigekey) {
// 声明一个空字符串用来存放加密后的密文
String message = "";
// for循环对字符串中每个字符进行加密操作
for (int i = 0; i < criphertext.length(); i++) {
// 字符变量用于存放依次取出的字符串中的字符
char c = criphertext.charAt(i);
// 取出密文中每个字符对应的密钥
char v = vigekey.charAt(i % vigekey.length());
if (c >= 'A' && c <= 'Z') {// 密文中的大写字母的转换
if (v >= 'A' && v <= 'Z') {// 密钥是大写字母
c = (char) (((c - 'A') - (v - 'A') + 26) % 26 + 'A');
} else if (v >= 'a' && v <= 'z') {// 密钥是小写字母
c = (char) (((c - 'A') - (v - 'a') + 26) % 26 + 'A');
} else if (v >= '0' && v <= '9') {// 密钥是数字
c = (char) (((c - 'A') - (v - '0') + 26) % 26 + 'A');
}
} else if (c >= 'a' && c <= 'z') {// 密文是小写字母的转换
if (v >= 'A' && v <= 'Z') {// 密钥是大写字母
c = (char) (((c - 'a') - (v - 'A') + 26) % 26 + 'a');
} else if (v >= 'a' && v <= 'z') {// 密钥是小写字母
c = (char) (((c - 'a') - (v - 'a') + 26) % 26 + 'a');
} else if (v >= '0' && v <= '9') {// 密钥是数字
c = (char) (((c - 'a') - (v - '0') + 26) % 26 + 'a');
}
} else if (c >= '0' && c <= '9') {// 密文是数字的转换
if (v >= 'A' && v <= 'Z') {// 密钥是大写字母
c = (char) (((c - '0') - (v - 'A') + 10) % 10 + '0');
} else if (v >= 'a' && v <= 'z') {// 密钥是小写字母
c = (char) (((c - '0') - (v - 'a') + 10) % 10 + '0');
} else if (v >= '0' && v <= '9') {// 密钥是数字
c = (char) (((c - '0') - (v - '0') + 10) % 10 + '0');
}
}
message += c;
}
return message;
}
③具体应用
(1)问题描述:读一个文件a2.txt中的字符,利用维吉尼亚密码算法加密,并将密文写入b2.txt,将解密出来的明文写入c2.txt。
(2)代码实现
import java.io.*;
import java.util.Scanner;
public class VigenereDemo2 {
public static void main(String[] args) throws IOException {
// File类的实例化
File file1 = new File("E:\\a1.txt");
// 用于存放读取到的文件的内容
String plaintext = ReadFile(file1);
// 输出明文文件
System.out.println("文件a1中的原文为:\n" + plaintext);
// 输入密钥
System.out.println("请输入密钥:");
Scanner s = new Scanner(System.in);
// 获取输入的密钥
String vigekey = s.nextLine();
// 调用加密方法
String cripher = Encryption(plaintext, vigekey);
// 输出加密后的内容
System.out.println("文件加密后的内容为:\n" + cripher);
// 文件名和文件保存的路径
File file2 = new File("E:\\b1.txt");
// 把密文写入到文件中去
writeFile(file2, cripher);
// 写入完成
System.out.println("文件已进行加密并保存在b1中!");
// 调用解密方法
String message = Decryption(plaintext, vigekey);
// 输出解密后的内容
System.out.println("文件解密后的内容为:\n" + message);
// 文件名和文件路径
File file3 = new File("E:\\c1.txt");
// 把解密后的明文写入到文件中
writeFile(file3, message);
// 写入完成
System.out.println("文件已进行加密并保存在c1中!");
}
// 读取文件方法
public static String ReadFile(File file) throws IOException {
// FileReader流的实例化
FileReader fr = new FileReader(file);
// 将字符流放入字符流缓冲区中
BufferedReader bf = new BufferedReader(fr);
// 声明一个字符串数组,用于接收读取的文档内容
StringBuffer sb = new StringBuffer();
// 定义一个字符串变量用于接收读取的文件内容
String Line;
// 按行读取
while ((Line = bf.readLine()) != null) {
//将读取到的字符串放入到字符串数组中
sb.append(Line);
sb.append("\n");
}
// 将字符串数组转为字符串
String s = new String(sb);
// 关闭流
bf.close();
fr.close();
return s;
}
// 写文件方法
public static void writeFile(File file, String content) throws IOException {
//filewriter流的实例化
FileWriter fw = new FileWriter(file);
//将字符流放入到字符流缓冲区中
BufferedWriter bw = new BufferedWriter(fw);
//进行写出操作
bw.write(content);
//关闭流
bw.close();
}
// 加密算法
public static String Encryption(String plaintext, String vigekey) {
// 声明一个空字符串用来存放加密后的密文
String cipher = "";
// for循环对字符串中每个字符进行加密操作
for (int i = 0; i < plaintext.length(); i++) {
// 字符变量用于存放依次取出的字符串中的字符
char p = plaintext.charAt(i);
// 取出明文中每个字符对应的密钥
char v = vigekey.charAt(i % vigekey.length());
if (p >= 'A' && p <= 'Z') {// 明文中的大写字母的转换
if (v >= 'A' && v <= 'Z') {// 密钥是大写字母
p = (char) (((p - 'A') + (v - 'A')) % 26 + 'A');
} else if (v >= 'a' && v <= 'z') {// 密钥是小写字母
p = (char) (((p - 'A') + (v - 'a')) % 26 + 'A');
} else if (v >= '0' && v <= '9') {// 密钥是数字
p = (char) (((p - 'A') + (v - '0')) % 26 + 'A');
}
} else if (p >= 'a' && p <= 'z') {// 明文是小写字母的转换
if (v >= 'A' && v <= 'Z') {// 密钥是大写字母
p = (char) (((p - 'a') + (v - 'A')) % 26 + 'a');
} else if (v >= 'a' && v <= 'z') {// 密钥是小写字母
p = (char) (((p - 'a') + (v - 'a')) % 26 + 'a');
} else if (v >= '0' && v <= '9') {// 密钥是数字
p = (char) (((p - 'a') + (v - '0')) % 26 + 'a');
}
} else if (p >= '0' && p <= '9') {// 明文是数字的转换
if (v >= 'A' && v <= 'Z') {// 密钥是大写字母
p = (char) (((p - '0') + (v - 'A')) % 10 + '0');
} else if (v >= 'a' && v <= 'z') {// 密钥是小写字母
p = (char) (((p - '0') + (v - 'a')) % 10 + '0');
} else if (v >= '0' && v <= '9') {// 密钥是数字
p = (char) (((p - '0') + (v - '0')) % 10 + '0');
}
}
cipher += p;
}
return cipher;
}
// 解密算法
public static String Decryption(String criphertext, String vigekey) {
// 声明一个空字符串用来存放加密后的密文
String message = "";
// for循环对字符串中每个字符进行加密操作
for (int i = 0; i < criphertext.length(); i++) {
// 字符变量用于存放依次取出的字符串中的字符
char c = criphertext.charAt(i);
// 取出密文中每个字符对应的密钥
char v = vigekey.charAt(i % vigekey.length());
if (c >= 'A' && c <= 'Z') {// 密文中的大写字母的转换
if (v >= 'A' && v <= 'Z') {// 密钥是大写字母
c = (char) (((c - 'A') - (v - 'A') + 26) % 26 + 'A');
} else if (v >= 'a' && v <= 'z') {// 密钥是小写字母
c = (char) (((c - 'A') - (v - 'a') + 26) % 26 + 'A');
} else if (v >= '0' && v <= '9') {// 密钥是数字
c = (char) (((c - 'A') - (v - '0') + 26) % 26 + 'A');
}
} else if (c >= 'a' && c <= 'z') {// 密文是小写字母的转换
if (v >= 'A' && v <= 'Z') {// 密钥是大写字母
c = (char) (((c - 'a') - (v - 'A') + 26) % 26 + 'a');
} else if (v >= 'a' && v <= 'z') {// 密钥是小写字母
c = (char) (((c - 'a') - (v - 'a') + 26) % 26 + 'a');
} else if (v >= '0' && v <= '9') {// 密钥是数字
c = (char) (((c - 'a') - (v - '0') + 26) % 26 + 'a');
}
} else if (c >= '0' && c <= '9') {// 密文是数字的转换
if (v >= 'A' && v <= 'Z') {// 密钥是大写字母
c = (char) (((c - '0') - (v - 'A') + 10) % 10 + '0');
} else if (v >= 'a' && v <= 'z') {// 密钥是小写字母
c = (char) (((c - '0') - (v - 'a') + 10) % 10 + '0');
} else if (v >= '0' && v <= '9') {// 密钥是数字
c = (char) (((c - '0') - (v - '0') + 10) % 10 + '0');
}
}
message += c;
}
return message;
}
}