凯撒密码(java & python)

      凯撒密码是对称密码体系的代表,其原理简单点说就是原字母移动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]+" ");
		}
	}
}

运行结果:

java

     

        当然如果你对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)

运行结果:

python

猜你喜欢

转载自blog.csdn.net/qq_41199831/article/details/83039079