> 文档中心 > Java加密算法—凯撒加密实现以及暴力破解

Java加密算法—凯撒加密实现以及暴力破解

目录

  • 1、概念
  • 2、加密实现
  • 3、解密实现
  • 4、频率分析法破解

1、概念

凯撒密码最早由古罗马军事统帅盖乌斯·尤利乌斯·凯撒在军队中用来传递加密信息,故称凯撒密码。这是一种位移加密方式,只对26个字母进行位移替换加密,规则简单,容易破解,恺撒密码通常被作为其他更复杂的加密方法中的一个步骤。

将明文字母表向后移动1位,A变成了B,B变成了C……,Z变成了A。因为字母移动26位会回到原值,移动27位的结果和移动1位是一样,所以字母表最多可以移动25位。

2、加密实现

public class KaiserTest {    public static void main(String[] args) { String text = "KaiserTest"; System.out.println("凯撒加密前原文:" + text); // 测试移动3位,进行加密 String encryptKaiser = encryptKaiser(text, 3); System.out.println("凯撒加密后密文:" + encryptKaiser);    }    /     * 使用凯撒加密方式加密数据     *     * @param original :原文     * @param key      :位移数量     * @return :加密后的数据     */    public static String encryptKaiser(String original, int key) { // 将字符串转为字符数组 char[] chars = original.toCharArray(); StringBuilder sb = new StringBuilder(); for (char aChar : chars) {     // 获取字符的ascii编码     int asciiCode = aChar;     // 偏移数据     asciiCode += key;     // 将偏移后的数据转为字符     char result = (char) asciiCode;     // 拼接数据     sb.append(result); } return sb.toString();    }}

效果:
在这里插入图片描述

3、解密实现

public class KaiserTest {    public static void main(String[] args) { String text = "KaiserTest"; System.out.println("凯撒加密前原文:" + text); // 测试移动3位,进行加密 String encryptKaiser = encryptKaiser(text, 3); System.out.println("凯撒加密后密文:" + encryptKaiser); // 解密操作 String decryptKaiser = decryptKaiser(encryptKaiser, 3); System.out.println("凯撒解密后明文:" + decryptKaiser);    }/     * 使用凯撒加密方式解密数据     *     * @param encryptedData :密文     * @param key    :位移数量     * @return : 源数据     */    public static String decryptKaiser(String encryptedData, int key) { // 将字符串转为字符数组 char[] chars = encryptedData.toCharArray(); StringBuilder sb = new StringBuilder(); for (char aChar : chars) {     // 获取字符的ASCII编码     int asciiCode = aChar;     // 偏移数据     asciiCode -= key;     // 将偏移后的数据转为字符     char result = (char) asciiCode;     // 拼接数据     sb.append(result); } return sb.toString();    } /     * 使用凯撒加密方式加密数据     *     * @param original :原文     * @param key      :位移数量     * @return :加密后的数据     */    public static String encryptKaiser(String original, int key) { // 将字符串转为字符数组 char[] chars = original.toCharArray(); StringBuilder sb = new StringBuilder(); for (char aChar : chars) {     // 获取字符的ascii编码     int asciiCode = aChar;     // 偏移数据     asciiCode += key;     // 将偏移后的数据转为字符     char result = (char) asciiCode;     // 拼接数据     sb.append(result); } return sb.toString();    }}

效果:
在这里插入图片描述

4、频率分析法破解

使用凯撒加密对字母表进行加密时,采用的是位移方法,如果分析出了合理的位移值,那么就可以对密文进行破解,英文字母出现频率最高的分别是e、t、a……,然后检查要破解的密文,也将每个字母出现的频率整理出来,假设密文中出现频率最高的字母是c,那么明文可能是e,如果密码文中出现频率次高的但是e,那么明文可能是t,以此类推便就能解开加密信息的内容,这就是频率分析法。

字母出现批量对照表-来自百度百科:
在这里插入图片描述在这里插入图片描述
代码演示:

public class KaiserAnalysisTest {    public static void main(String[] args) { // 字母频率排名 char[] orderChar = {'e', 't', 'a', 'o', 'n', 'r', 'i', 's', 'h',  'd', 'l', 'f', 'c', 'm', 'u', 'g', 'y', 'p', 'w', 'b',  'v', 'k', 'j', 'x', 'q', 'z'}; // 明文,用于最后进行对比 String text = "Encrypt the alphabet using Caesar encryption"; // 加密后密文,用于破解 String secret = "Hqfu|sw#wkh#doskdehw#xvlqj#Fdhvdu#hqfu|swlrq"; // 打印各字符出现数量 List<Map.Entry<Character, Integer>> mapList = countChars(secret); // 匹配概率值 out: for (char ch : orderChar) {     for (Map.Entry<Character, Integer> entry : mapList) {  System.out.println("猜测最大概率字符为:" + ch);  Character key = entry.getKey();  int keyNum = key - ch;  System.out.println("猜测key为:" + key + ",与" + ch + "的ASCII相差:" + keyNum);  // 根据偏移值解密  String decryptData = decryptKaiser(secret, keyNum);  System.out.println("解密后明文预计为:" + decryptData);  boolean result = decryptData.equals(text);  System.out.println("是否复合条件:" + result);  if (result) {      break out;  }     } }    }    /     * 解密     *     * @param secret     * @param key     * @return     */    public static String decryptKaiser(String secret, int key) { // 1、将密文转换成字符数组 char[] chars = secret.toCharArray(); StringBuilder sb = new StringBuilder(); for (char aChar : chars) {     // 2、获取字符的ascii编码     int asciiCode = aChar;     // 3、偏移数据     asciiCode += key;     // 4、将偏移后的数据转为字符     char result = (char) asciiCode;     // 5、拼接数据     sb.append(result); } return sb.toString();    }    /     * 统计String里出现最多的字符     *     * @param data     */    public static List<Map.Entry<Character, Integer>> countChars(String data) { //创建TreeMap集合,键是Character,值是Integer Map<Character, Integer> map = new HashMap<>(16); //遍历字符串,得到每一个字符 for (int i = 0; i < data.length(); i++) {     char key = data.charAt(i);     //拿到每一个字符作为键到TreeMap集合中去找对应的值,看其返回值     Integer value = map.get(key);     //如果返回值是null,说明该字符在TreeMap集合中不存在,就把该字符串作为键,1作为值存储     if (value == null) {  map.put(key, 1);     } else {  //如果返回值不是null,说明该字符在TreeMap集合中存在,把该值加一,然后重新存储该字符和对应的值  value++;  map.put(key, value);     } } // 对结果进行排序 List<Map.Entry<Character, Integer>> mapList = new ArrayList<>(map.entrySet()); //根据字符出现次数排序 mapList.sort((o1, o2) -> o2.getValue().compareTo(o1.getValue())); StringBuilder sb = new StringBuilder(); //遍历Map集合,得到键和值,按照要求进行拼接 mapList.forEach(entry -> {     Integer value = entry.getValue();     Character key = entry.getKey();     sb.append(key).append("出现").append(value).append("次; "); }); //调用toString方法,从StringBuilder转为String类型输出 String result = sb.toString(); System.out.println(result); return mapList;    }}

效果:
Java加密算法—凯撒加密实现以及暴力破解
注意:key指的是当前验证的密文的字符