package Vigenère;
public class VigenèreCracker {
private static final double LETTER_FREQUENCY[] = { 0.0788, 0.0156, 0.0268,
0.0389, 0.1268, 0.0256, 0.0187, 0.0573, 0.0707, 0.0010, 0.0060,
0.0394, 0.0244, 0.0706, 0.0776, 0.0186, 0.0009, 0.0594, 0.0634,
0.0978, 0.0280, 0.0102, 0.0214, 0.0016, 0.0202, 0.0006 };// 26个英文字母在正常英文中出现的概率
/**
* Vigenère密码的破解
*
* @param String
* ciphertext
* @return String key
*/
public static String cracker(String ciphertext) {
String key = "", // 存放密钥
tempCiphertext = "";// 存放将密文分组后的同组密文
int keyLength = 0, // 密钥长度
row = 0, // 密文所分成的列数,不记最后一行
last_length = 0, // 最后一行长度
ciphertextLength;// 密文长度
ciphertext = initialize(ciphertext);//初始化密文
ciphertextLength = ciphertext.length();// 获得密文长度
keyLength = getKeyLength(getRate(ciphertext));// 调用获取密码长度函数
row = (int) ciphertextLength / keyLength;// 获取整数位个行
last_length = ciphertextLength % keyLength;// 如最后一行个数小于密钥长度,则存放最后一行的密文个数
for (int i = 0; i < keyLength; i++) {
tempCiphertext = "";
for (int j = 0; j < row; j++) {// 把密文分组
tempCiphertext += ciphertext.charAt(keyLength * j + i);// 从整数组当中抽取同组密文
}
if (last_length > i) {
tempCiphertext += ciphertext.charAt(keyLength * row + i);// 从最后余下的密文中抽取同组密文
}
key += getValue(getRate(tempCiphertext));// 通过生成的每组密文,分别求出移位的加密字母,并合成完整的密钥
}
return key;
}
/*
* 初始化函数
*/
private static String initialize(String ciphertext) {
String initialized = "";
ciphertext = ciphertext.toLowerCase();// 将大写字母转化为小写字母
for (int i = 0; i < ciphertext.length(); i++) {
char temp = ciphertext.charAt(i);
if (temp >= 'a' && temp <= 'z')// 将密文中的非字母全部除去
initialized += temp;
}
return initialized;
}
/*
* 获取文本中26个字母出现的概率
*/
private static double[] getRate(String text) {
double[] rate = new double[26];
int length = 0;
for (int i = 0; i < text.length(); i++) {
char temp = text.charAt(i);
if (temp >= 'a' && temp <= 'z') {//剔除出小写字母外的一切字母
rate[temp - 97]++;
length++;
}
}
for (int i = 0; i < 26; i++) {
rate[i] /= length;
}
return rate;
}
/*
* 破解密钥的长度
*/
private static int getKeyLength(double[] rate) {
double length = 0.0, IC = 0.0;
for (int i = 0; i < rate.length; i++) {
IC += (rate[i] * rate[i]);// 计算出重合指数
}
length = ((0.0687 - 0.0385) / (IC - 0.0385));// 通过公式得出密钥的长度
//对密钥长度四舍五入
if (length % (int) length < 0.5)
return (int) length;
else
return (int) (length + 1);
}
/*
* 移位破解单个加密字符
*/
private static char getValue(double[] rate) {
int Offset = 0;//位移个数
double sum = 0.0, d = 0.0, min = 1.0;// 记录与0.065差值最小的数
for (int i = 0; i < 26; i++) {
for (int j = i; j < i + 26; j++) {
sum += rate[j % 26] * LETTER_FREQUENCY[j - i];//移位计算出重合指数
}
//获取最接近0.065的值
d = Math.abs(sum - 0.065);
if (d < min) {
min = d;
Offset = i;
}
sum = 0;
}
return (char) (Offset + 97);//返回解出的加密字符
}
}
- 1
- 2
前往页