前鱼不泣 2022-02-25 14:11 采纳率: 81.8%
浏览 71
已结题

java 破解凯撒密码

跟参数输出范例一样就行。得用他给的变量名。其它就是凯撒密码的形式,变成不需要key就行破译,根据图片里的频率(那个表格就是给出的频率)

img

img

  • 写回答

2条回答 默认 最新

  • qq_34370249 2022-02-25 16:37
    关注
    
    package com.zhengtao;
    
    /*
     * @Description :
     * @CreateTime : 2022-02-25 15:36
     */
    public class Demo {
    
        /**
         * 这个 是 明文?
         */
        public static final double[] ENGLISH = {
                0.0855, 0.0160, 0.0316, 0.0387, 0.1210, 0.0218, 0.0209, 0.0496, 0.0733,
                0.0022, 0.0081, 0.0421, 0.0253, 0.0717, 0.0747, 0.0207, 0.0010, 0.0633,
                0.0673, 0.0894, 0.0268, 0.0106, 0.0183, 0.0019, 0.0172, 0.0011
        };
    
        /*
         * @Description: 这个 main 方法用来破解 凯撒密码
         * 首先了解,什么是凯撒密码,凯撒加密(Caesar Code)是一种简单的消息编码方式:它根据字母表将消息中的每个字母移动常量位k。
         * 举个例子如果k等于3,则在编码后的消息中,每个字母都会向前移动3位:a会被替换为d;b会被替换成e;
         * 依此类推。字母表末尾将回卷到字母表开头。于是,w会被替换为z, x会被替换为a。在解码消息的时候,每个字母会反方向移动同样的位数。
         * 那么 如何破解 凯撒密码,已经很简单明了了,
         * @Date: 2022-02-25 16:00
         * @param args
         * @Return: void
        */
        public static void main(String[] args) {
            // 这里应该是从命令行读取的,我这里,不方便 从命令行读取,我直接写死了,题主 这里自己处理一下
            String ciphertext = "asjfkljasklfjlkasjdklfjklaskldjfasfdd";
            // 从题目中看, EngLish  应该是,最终比对的明文
            // 手动实现 解密凯撒密码
            String temp = "";
            int count = 1;
            while(true){
                temp = "";
                for (int i = 0; i < ciphertext.length(); i++) {
                    // 确保 输入的字母 是 字母
                    if ((ciphertext.charAt(i) > 'a' && ciphertext.charAt(i) < 'z') || (ciphertext.charAt(i) > 'A' && ciphertext.charAt(i) < 'Z')){
                        char ch = (char) (ciphertext.charAt(i) + count);
                        // 凯撒编码
                        if (ch > 106 && ch < 97){
                            ch = (char) (ch - 26);
                        }
                        if (ch > 122){
                            int l = ch - 97;
                            ch = (char) (ch - 26);
                        }
                        temp = ch + temp;
                    }
                }
                count++;
                System.out.println("开始执行 -> " + temp);
                if (chiSquared(frequency(temp), ENGLISH) == 0){
                    break;
                }
                if (count == 26){
                    temp = "";
                    break;
                }
            }
            if (temp.equals("")){
                System.out.println("输入与明文不对应");
            }else {
                System.out.println("破解成功 -> " + temp);
            }
        }
    
    
        /*
         * @Description: 返回 String 中 每个字母出现的次数
         * @Date: 2022-02-25 15:37
         * @param str
         * @Return: int[]
        */
        public static int[] count(String str){
            int[] res = new int[26];
            char[] chars = str.toCharArray();
            for (char ch : chars) {
                // 小写字母
                if(ch - 65 >= 0 && ch - 65 <=25){
                    res[ch - 65]++;
                }
                // 大写字母
                if (ch - 97 >= 0 && ch - 97 <= 25){
                    res[ch - 97]++;
                }
            }
            return res;
        }
    
    
    
        public static double[] frequency(String str){
            double[] res = new double[26];
            // 每个字母出现的频率
            int[] count = count(str);
            // 给定字符串的长度
            int length = str.length();
            for (int i = 0; i < count.length; i++) {
                res[i] = count[i] / length;
            }
            return res;
        }
    
        /**
         * @Description: 求出来 两个数组到底有多接近   如果两个数组,一模一样,则返回结果 为 0, 匹配度越高,则返回值 越小
         * @Date: 2022-02-25 15:53
         * @param freq
         * @param english
         * @Return: double
        */
        public static double chiSquared(double[] freq, double[] english){
            if (freq.length != english.length){
                return -1;
            }
            double res = 0.0;
            double[] temp = new double[26];
            // 求出 a - z的匹配度
            for (int i = 0; i < freq.length; i++) {
                temp[i] = (freq[i] - english[i]) * (freq[i] - english[i]) / english[i];
            }
            // 根据公式,将结果求和
            for (double v : temp) {
                res += v;
            }
            return res;
        }
    }
    
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
查看更多回答(1条)

报告相同问题?

问题事件

  • 系统已结题 3月6日
  • 已采纳回答 2月26日
  • 创建了问题 2月25日

悬赏问题

  • ¥15 yolov8边框坐标
  • ¥15 matlab中使用gurobi时报错
  • ¥15 WPF 大屏看板表格背景图片设置
  • ¥15 这个主板怎么能扩出一两个sata口
  • ¥15 不是,这到底错哪儿了😭
  • ¥15 2020长安杯与连接网探
  • ¥15 关于#matlab#的问题:在模糊控制器中选出线路信息,在simulink中根据线路信息生成速度时间目标曲线(初速度为20m/s,15秒后减为0的速度时间图像)我想问线路信息是什么
  • ¥15 banner广告展示设置多少时间不怎么会消耗用户价值
  • ¥16 mybatis的代理对象无法通过@Autowired装填
  • ¥15 可见光定位matlab仿真