凯撒密码是对称密码体系的代表,其原理简单点说就是原字母移动k个位置后用k位置处的字母代表之前的字母。下面给出我写的破解凯撒密码体系的初次尝试(暴力破解)。程序思路大致就是对密文做适当处理,去掉标点符号等一些会影响我们后续工作的字符,再将其分解为逐个单词,再将单词分解为字符,然后从1~26中选一个可能的位移量(密钥)求出其对应的可能解,如此一来将得到26组可能解,再将得到的可能解与事先准备好的100个常用单词做比较,选出匹配成功个数最大的对应的位移量下的可能解,此解就是破解的结果,(说了半天我都不知道在说啥,还是看代码吧)先看Java详细实现,后面还有Python的版本!
package xinxianquan;
/**
* @author node
*
*/
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class kaisa {
public static void main(String[] args) {
// String url_m="./cipher.txt";
String url_m="./Emessage.txt";
String url_w="./words.txt";
//将密文信息录入并处理保存在message字符串中
String message=readMessage(url_m, 1);
System.out.println("密文信息:"+message);
//破解
long startTime=System.currentTimeMillis(); //获取开始时间
searchK(splitMessage(message), url_w);
long endTime=System.currentTimeMillis(); //获取结束时间
System.out.println("\n解密用时"+(endTime-startTime)+"ms");
}
//读取文件内容方法
public static String readMessage(String url,int flag) {
String message="";
String line;
try {
BufferedReader re =new BufferedReader(new FileReader(url));
line=re.readLine();
message =line;
while(line != null) {
line = re.readLine();
if(line!=null && flag==0) {//0用来读取words。
message+=" "+line;
}else if(line!=null){
message+=line;
}
}
re.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return message;
}
//处理字符串,得到可能的解集
public static String[][] splitMessage(String message) {
//将句子拆分为单词(即出去空格和一些标点符号,此处给出空格、句号、感叹号和逗号,这些符号的存在会影响我们后期的处理)
String [] result=message.split(" |\\.|!|,");
//创建一个二维字符串数组,有26行,对应k的26种可能取值,result.length列表示每行都有这么多的单词
String[][] maybeMessage =new String[26][result.length];
//循环26次,每次都是一种k的可能取值。先将所有分割出来的单词分解为字符,保存在字符数组中(letter)
//然后再将这些字符均往后移动k个位置,得到位移量可能为k的一种解
//再将这种可能的解还原为字符串(单词)保存到maybeMessage中对应行的对应列中。
//循环完26次后就得到了所有可能的解
for(int k=0;k<26;k++) {
for(int i=0;i<result.length;i++) {
char[] letter = result[i].toCharArray();//将划分得到的单词逐个变成字符数组
for(int j=0;j<letter.length;j++) {
letter[j]=(char) ((letter[j]-'a'+(26-k+1))%26+'a');//将所得的字符数组逐个移动k个单位得到可能的解
}
//将转换后的字符数组转回字符串(单词)的形式存储起来
maybeMessage[k][i]=String.valueOf(letter);
}
}
return maybeMessage;
}
//逐个匹配准备好的单词,常理上来说匹配到的单词越多,准确率越高
public static void searchK(String[][] maybeMessage,String url) {
//下面语句可以列出所有k值下破解的结果
// for(int i=0;i<maybeMessage.length;i++) {
// System.out.print("key="+(i+1)+": ");
// for(int j=0;j<maybeMessage[0].length;j++) {
// System.out.print(maybeMessage[i][j]+" ");
// }
// System.out.println();
// }
//首先将准备好的单词读入一个字符串数组中准备好配备
int[] num=new int[26];
for(int i=0;i<26;i++) {
num[i]=0;
}
//读入的一个字符串用空格分割成多个单词
String[] word=readMessage(url, 0).split(" ");
// writerMessage("./wordline.txt",readMessage(url, 0));
//暴力破解代码段
for(int k=0;k<26;k++) {
for(int i=0;i<maybeMessage[0].length;i++) {
for(int j=0;j<word.length;j++) {
//匹配到其中之一,num对应值加1,结束这个单词本次匹配,进入下一个单词的匹配
if(maybeMessage[k][i].equals(word[j])) {
num[k]++;
break;
}
}
}
}
//跑完三重循环,得到了每种k值下匹配成功的单词个数,求出成功匹配单词数最多的K
int max=0;
int key=0;
for(int i=0;i<num.length;i++) {
if(num[i]>max) {
max=num[i];
key=i;
}
}
//输出k=key时的字符串
System.out.println("密钥是:"+(key-1));
System.out.print("解密后的明文信息:");
for(int i=0;i<maybeMessage[key].length ;i++) {
System.out.print(maybeMessage[key][i]+" ");
}
}
}
运行结果:
当然如果你对Python更情有独钟,请看如下代码,思想是一样的,只不过Python太强大,几行代码就能实现,但是Java的实现过程对凯撒密码的理解会更深刻!
#!/usr/bin/env python3
# _*_ coding: utf-8 _*_
import re
import time
__author__ = 'Node'
def encryption(Emessage, key):
change = []
message = list(Emessage.lower())
for letter in message:
if letter>= 'a' and letter <= 'z':
letter = chr((ord(letter) - ord('a') + 26 - key) % 26 + ord('a'))
change.append(letter)
else:
change.append(letter)
continue
return ''.join(change)
def search_key(mabeyMessage,words):
result = []
n = 0
result = re.split(' |,|\.|!|\?',mabeyMessage)
for em in result:
if em in words.split():
n = n + 1
return n
if __name__ == '__main__':
with open('./Emessage.txt') as ef:#cipher
Emessage = ef.read()
with open('./wordline.txt')as wf:
words = wf.read()
pipei =[]
max = 0
K = 0
start = time.perf_counter()
for i in range(1,27):
pipei.append(search_key(encryption(Emessage,i),words))
if pipei[i-1] > max:
max = pipei[i-1]
K = i
end = time.perf_counter()
print('密文信息:',Emessage)
print('密钥是:k=',K)
print('明文信息:',encryption(Emessage,K))
print('解密用时:%s Seconds'%( end - start ))
#加密用法
m1 = 'what can I do for you?'
e1=encryption(m1,3)
print('加密后:',e1)
运行结果: