【Java】基于朴素贝叶斯算法破解基于哈希表的随机字符替换加密算法

2023-11-18

【Java】基于朴素贝叶斯算法破解基于哈希表的随机字符替换加密算法
  不用看了,这篇文章是错的。得出的结果也不是正确的结果。我想错了,因为这个解密算法的前提是已经知道哈希表的情况下去计算的。而实际上应该是只靠统计去分析密文,所以实际破解所需要的密文字符数应该是要大于本文所计算出来的那张图

前言

  本文介绍了关于使用基于朴素贝叶斯算法训练模型破解随机字符替换加密算法,并通过解密后的数据统计对加密算法进行安全性分析。


摘要

  本文研究了基于哈希表的随机字符替换加密算法及其安全性问题,采用朴素贝叶斯算法对该加密算法进行破解,并对破解结果进行分析和讨论。研究结果表明,该加密算法的安全性不足,易被破解。本文提出了改进措施,提高了算法的安全性。

关键词:哈希表、随机字符替换加密、朴素贝叶斯算法、安全性


一、代码部分

代码部分如下所示:

import javax.swing.*;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.List;
import java.util.*;

public class Main {
    private static final int WIDTH = 600;
    private static final int HEIGHT = 400;
    private static final int BORDER_GAP = 30;
    private static final Color LINE_COLOR = Color.BLUE;
    private static final Stroke GRAPH_STROKE = new BasicStroke(2f);
    private static final int GRAPH_POINT_WIDTH = 6;


    public static void main(String[] args) {

        //读取哈希表
        Map<Character, List<Character>> hashTable;
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("hashtable.ser"))) {
            hashTable = (Map<Character, List<Character>>) ois.readObject();
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
            return;
        }
        NaiveBayes naiveBayes = null;
        ArrayList<Double> accuracyList = new ArrayList<>();
        ArrayList<Integer> lengthList = new ArrayList<>();
        for (int times = 0; times < 1000000; times += 1000) {
            lengthList.add(times);
            int length = 1;
            //生成10000个长度为100的字符串
            Random random = new Random();

            List<String> originalStrings = getOriginalStrings(times, length, random);

            List<String> encryptedStrings = getEncryptedStrings(hashTable, originalStrings, random);

            Map<String, String> dataSet = getStringStringMap(originalStrings, encryptedStrings);

            //使用朴素贝叶斯算法训练出一个解密的模型
            naiveBayes = new NaiveBayes();
            naiveBayes.train(dataSet);

            accuracyList.add(accuracyTest(hashTable, length, random, naiveBayes));
            if (accuracyList.get(accuracyList.size() - 1) > 0.99) {
                System.out.println("准确率(0~1): " + accuracyList.get(accuracyList.size() - 1));
                System.out.println("截取密文长度:" + times + '\n');
                break;
            }
        }
        drawGraph(accuracyList, lengthList, 20000, 0.1);

        Scanner scanner = new Scanner(System.in);

        System.out.println("请输入要解密的密文:");
        String encryptedString = scanner.nextLine();

        System.out.println("解密结果:\n" + naiveBayes.predict(encryptedString));
    }

    private static List<String> getOriginalStrings(int times, int length, Random random) {
        List<String> originalStrings = new ArrayList<>();
        for (int i = 0; i < times; i++) {
            StringBuilder sb = new StringBuilder();
            for (int j = 0; j < length; j++) {
                int r = random.nextInt(36);
                if (r < 26) {
                    sb.append((char) ('a' + r));
                } else if (r < 35) {
                    sb.append((char) ('0' + r - 26));
                } else {
                    sb.append(' ');
                }
            }
            originalStrings.add(sb.toString());
        }
        return originalStrings;
    }

    private static List<String> getEncryptedStrings(Map<Character, List<Character>> hashTable, List<String> originalStrings, Random random) {
        //将这些字符串通过哈希表进行加密
        List<String> encryptedStrings = new ArrayList<>();
        for (String originalString : originalStrings) {
            StringBuilder sb = new StringBuilder();
            for (char c : originalString.toCharArray()) {
                sb.append(hashTable.get(c).get(random.nextInt(hashTable.get(c).size())));
            }
            encryptedStrings.add(sb.toString());
        }
        return encryptedStrings;
    }

    private static Map<String, String> getStringStringMap(List<String> originalStrings, List<String> encryptedStrings) {
        //将生成的密文和原字符串一一对应起来
        Map<String, String> dataSet = new HashMap<>();
        for (int i = 0; i < originalStrings.size(); i++) {
            dataSet.put(encryptedStrings.get(i), originalStrings.get(i));
        }
        return dataSet;
    }

    private static double accuracyTest(Map<Character, List<Character>> hashTable, int length, Random random, NaiveBayes naiveBayes) {
        int timesTest = 100000;
        //生成10000个随机字符,用哈希表进行加密后,再用训练出的模型进行解密
        List<String> testStrings = getOriginalStrings(timesTest, length, random);
        //用哈希表加密
        List<String> testEncryptedStrings = getEncryptedStrings(hashTable, testStrings, new Random());
        //用训练出的模型进行解密
        List<String> testDecryptedStrings = new ArrayList<>();
        for (String testEncryptedString : testEncryptedStrings) {
            testDecryptedStrings.add(naiveBayes.predict(testEncryptedString));
        }

        //将解密结果与原字符进行对比,评测模型的准确度并打印到输出台上
        int correctCount = 0;
        for (int i = 0; i < testStrings.size(); i++) {
            if (testStrings.get(i).equals(testDecryptedStrings.get(i))) {
                correctCount++;
            }
        }
        return correctCount / (double) timesTest;
    }

    public static void drawGraph(ArrayList<Double> accuracyList, ArrayList<Integer> lengthList, int xUnitLength, double yUnitLength) {
        JFrame frame = new JFrame("统计测试");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(WIDTH, HEIGHT);

        JPanel panel = new JPanel() {
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                Graphics2D g2 = (Graphics2D) g;

                g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                setBackground(Color.WHITE);

                //绘制坐标系
                g2.drawLine(BORDER_GAP, getHeight() - BORDER_GAP, BORDER_GAP, BORDER_GAP);
                g2.drawLine(BORDER_GAP, getHeight() - BORDER_GAP, getWidth() - BORDER_GAP, getHeight() - BORDER_GAP);

                //绘制数据点和连线
                int pointX, pointY, prevPointX = 0, prevPointY = 0;
                for (int i = 0; i < accuracyList.size(); i++) {
                    pointX = (int) ((double) (getWidth() - 2 * BORDER_GAP) / (lengthList.size() - 1) * i + BORDER_GAP);
                    pointY = (int) ((getHeight() - 2 * BORDER_GAP) * (1 - accuracyList.get(i)) + BORDER_GAP);
                    g2.setColor(LINE_COLOR);
                    g2.setStroke(GRAPH_STROKE);
                    if (i > 0) {
                        g2.drawLine(prevPointX, prevPointY, pointX, pointY);
                    }
                    g2.fillOval(pointX - GRAPH_POINT_WIDTH / 2, pointY - GRAPH_POINT_WIDTH / 2, GRAPH_POINT_WIDTH, GRAPH_POINT_WIDTH);
                    prevPointX = pointX;
                    prevPointY = pointY;
                    //在x轴上绘制坐标值
                    if (lengthList.get(i) % xUnitLength == 0) {
                        g2.drawString(String.format("%,d", lengthList.get(i)), pointX, getHeight() - BORDER_GAP / 2);
                    }
                }

                //在y轴上绘制坐标值
                for (int i = 0; i <= 10; i++) {
                    int y = (int) ((getHeight() - 2 * BORDER_GAP) * (1 - i * 0.1) + BORDER_GAP);
                    g2.drawString(String.format("%.1f", i * yUnitLength), BORDER_GAP / 2, y);
                }

                //在x轴下标注密文长度
                g2.drawString("密文长度", getWidth() / 2, getHeight() - BORDER_GAP / 4);

                //在y轴旁边标注准确率
                AffineTransform origTransform = g2.getTransform();
                AffineTransform at = new AffineTransform();
                at.rotate(-Math.PI / 2);
                g2.setTransform(at);
                g2.drawString("准确率", -getHeight() / 2, BORDER_GAP / 2);
                g2.setTransform(origTransform);
            }

            @Override
            public Dimension getPreferredSize() {
                return new Dimension(WIDTH, HEIGHT);
            }
        };

        frame.add(panel);
        frame.setVisible(true);
    }

    private static class NaiveBayes {
        private Map<String, Map<Character, Integer>> featureCount;
        private Map<String, Integer> labelCount;

        public NaiveBayes() {
            featureCount = new HashMap<>();
            labelCount = new HashMap<>();
        }

        public void train(Map<String, String> dataSet) {
            for (Map.Entry<String, String> entry : dataSet.entrySet()) {
                String encryptedString = entry.getKey();
                String originalString = entry.getValue();
                for (int i = 0; i < encryptedString.length(); i++) {
                    String feature = encryptedString.substring(i, i + 1);
                    char label = originalString.charAt(i);
                    if (!featureCount.containsKey(feature)) {
                        featureCount.put(feature, new HashMap<>());
                    }
                    if (!featureCount.get(feature).containsKey(label)) {
                        featureCount.get(feature).put(label, 0);
                    }
                    featureCount.get(feature).put(label, featureCount.get(feature).get(label) + 1);
                }
                if (!labelCount.containsKey(originalString)) {
                    labelCount.put(originalString, 0);
                }
                labelCount.put(originalString, labelCount.get(originalString) + 1);
            }
        }

        public String predict(String encryptedString) {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < encryptedString.length(); i++) {
                String feature = encryptedString.substring(i, i + 1);
                char label = 'a';
                int maxCount = 0;
                //若找不到字符对应的指针,则解出的密文赋与*字符
                if (!featureCount.containsKey(feature)) {
                    sb.append('*');
                    continue;
                }
                for (Map.Entry<Character, Integer> entry : featureCount.get(feature).entrySet()) {
                    if (entry.getValue() > maxCount) {
                        maxCount = entry.getValue();
                        label = entry.getKey();
                    }
                }
                sb.append(label);
            }
            return sb.toString();
        }
    }
}

二、基于哈希表的随机字符替换加密算法

基于哈希表的随机字符替换加密算法的加密过程如下:

  1. 随机生成一个包含37个字符的字符集,其中包括26个英文字母、0-9共10个数字和一个空格字符;
  2. 对于每个字符,随机分配一个Unicode编码的字符,共分配1771个字符,将这些字符用哈希表进行存储;
  3. 需要加密时,将明文中的每个字符替换为哈希表中的其他字符,即随机抽取一个哈希表中的字符进行替换。

更多关于这个加密算法的内容可以参考我之前的一篇文章:

【Java】基于哈希表的随机字符替换加密算法 --by 何故不嗣音


三、基于朴素贝叶斯算法训练模型

  朴素贝叶斯分类是一种基于贝叶斯定理和特征条件独立假设的分类方法。它可以用来对输入数据进行分类。它的假设是特征之间相互独立,这样可以简化计算。

  本代码中,朴素贝叶斯算法用于加密字符串的解密。首先,使用随机函数生成一定数量的原字符串,并将其通过哈希表进行加密,生成密文对。然后,使用朴素贝叶斯训练出一个解密的模型。

模型训练过程:

  1. 遍历数据集中的每一对密文和原文,将原文每个字符作为标签,将密文每个字符作为特征,计算每个特征在各标签中出现的频率,并存储在特征及其标签的计数器中。

  2. 对每个标签,计算在训练集中出现的次数,并存储在标签计数器中。

  3. 使用贝叶斯公式计算每个特征对应每个标签的概率,并将计算结果存储在模型中。

  训练完成后,对输入的密文,可以使用模型计算每个特征对应的标签概率,然后取概率最大的标签作为解密结果。


四、朴素贝叶斯算法破解基于哈希表的随机字符替换加密算法

  1. 准备数据集:
      随机生成一定数量的字符串,然后通过哈希表进行随机字符替换,将得到的密文与原字符串构成对应关系,作为训练数据集使用。

  2. 构建模型:
      采用朴素贝叶斯算法构建训练模型,计算每个字符被替换成另一个字符的概率。

  3. 破解并计算准确率:
      重新随机生成足够数量的字符串,同样通过基于哈希表的随机字符替换加密算法进行加密,得到测试集。根据训练出来的模型,利用朴素贝叶斯算法对测试集密文进行破解,计算并统计模型准确率。


五、安全性分析

  代码通过朴素贝叶斯算法对其进行破解,并统计绘制出密文字符个数与准确率的关系曲线。如下图所示:

  从图中曲线可以看出,模型在大概截取60000左右的密文字符数时,能破解百分之60~70的密文。截取100000左右的密文字符数时,能破解百分之八十左右的密文。所以安全性方面较差。


六、可行的改进方法

这里给出两种可行的改进加密算法,以增强其安全性的方法:

  1. 增加字符集字符个数:原有的字符集大小为37,可以通过增加字符集的个数,以增加加密的安全性,但是这种方式需要考虑到是否使用某个字符,然后再加入到字符集中。如果明文中没有必要使用某字符的话,那么也不需要加入,所以我认为通过这种方式加强加密的安全性并不方便。

  2. 增加为每个字符分配的字符个数:原有的分配个数为1771,可以通过增加为每个字符分配的字符个数的方式以提高加密的安全性。并且这种增加可以是无上限的,也就是在分配的字符个数足够多的情况下,可以无限提高该加密方式的安全性。


七、总结

  本文研究了基于哈希表的随机字符替换加密算法及其安全性问题,采用朴素贝叶斯算法对该加密算法进行破解,并对破解结果进行分析和讨论。结果表明,该加密算法的安全性不足,易被破解。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【Java】基于朴素贝叶斯算法破解基于哈希表的随机字符替换加密算法 的相关文章

随机推荐

  • 杂谈随感-2:创新是革新还是革命?

    革新 通常来自于一个系统内部 来自于现有系统的既得利益者 来自于系统内深谙其道的人 来自于系统内深根细作的人 革新者的首要目标是维持现有系统的存在和现有系统大多数人的利益 其二才是革新 革新的目标也是维持现有系统长期存在和发展 一个对现有系
  • SpringBoot集成hystrix

    文章目录 hystrix有什么用 在SpringBoot项目中集成 更多配置示例 配置线程池 配置信号量 配合feignClient使用 基本配置 可视化组件 视图hystrix dashboard 汇总监控turbine 参考 hystr
  • elementUI dialog 弹窗组件的使用-title 属性的文字提示 没有设置 center 属性但是居中了

    项目场景 elementUI dialog 弹窗组件的使用 问题描述 elementUI dialog 弹窗组件使用时 title 属性的文字提示 没有设置 center 属性但是居中了 原因分析 原因是在该组件的外层使用了 text al
  • Qt一个信号关联多个槽传输数据

    测试描述 一个TCP服务 三个处理线程 tcp接收的数据传输至三个线程使用 使用信号与槽进行通讯 信号与槽连接如下 关联1 connect tcpServer SIGNAL recBytes QByteArray panorama SLOT
  • Java Beans 介绍

    Java版本 8 写JavaBeans组件 编写JavaBeans组件非常简单 您不需要特殊的工具 也不需要实现任何接口 编写bean只是遵循某些编码约定的问题 您所要做的就是使您的类看起来像一个bean 使用bean的工具将能够识别和使用
  • 淘宝问问:电商AI,重新定义购物体验

    AI大模型进展的如火如荼 怎么少得了电商平台的参与 淘宝率先打响了第一枪 每一个软件都会有自己的 Copilot 淘宝的就叫 淘宝问问 用户可以在淘宝上使用 淘宝问问 来获取商品信息 价格 评价等 当前是内测版 虽有惊喜 但终究是刚刚发布内
  • 同态加密的原理详解与go实践

    学习资料来源 知乎VenusBlockChain https zhuanlan zhihu com p 110210315 知乎刘巍然 https www zhihu com question 27645858 answer 3759850
  • 空间注意力机制_计算机视觉中attention机制的理解

    一 前言 简介 对于attention机制的理解 在看了attention is all you need这篇文章和参考网上一些文章之后 做一个简单的理解和总结 在 attention is all you need 的这篇文章中给出了在n
  • PySide6-控件教程-006-QLabel标签控件-信号

    QLabel 标签控件 本文摘录自我的开源教程 PySide6 代码式教程 QLabel CSDN 平台仅做镜像 答疑 纠错请至 GitHub 提交 issue 信号 QLabel的可用信号只有链接被悬停 链接被点击两种 具体如下 link
  • 金融安全视角农民投资理财的实证研究——以X县为例

    金融安全视角农民投资理财的实证研究 以X县为例 摘要 近年来 随着经济全球化进程的推进 国民收入逐年增加 人们的经济意识也在一定程度上提高 适当的投资和财务管理正在迅速发展 然而 大部分调查数据显示 农民面临的诸多问题还有很多其他原因 包括
  • Qt技巧:QTextEdit显示网络图片

    Qt5的QNetworkAccessManager 类可以很方便的访问网络资源 QNetworkRequest类可以用于发送网络请求 而QNetworkReply则负责接收处理网络资源 今天遇到一个问题 如何在QTextEdit上显示一张网
  • 字节跳动(今日头条),为何战斗力如此凶猛?

    本文转载自公众号 中产之路 年前 一位久未联系的朋友问京杭君 有没有研究过今日头条 还有没有上升空间 这位朋友在杭州阿里工作多年 后出来创业 有猎头联系他 今日头条要在杭州成立技术中心 招负责人 那时候 今日头条 还是这间公司最重要的产品
  • 编辑器Vim

    vi简介 vi是 Visual interface 的简称 它在Linux上的地位就仿佛Edit程序在DOS上一样 它可以执行输出 删除 查找 替换 块操作等众多文本操作 而且用户可以根据自己的需要对其进行定制 Vi不是一个排版程序 它不象
  • 蓝牙耳机BES 2300P 主从配对连接,以及主从自定义收发数据

    恒玄SDk预留了用户接口位于app ibrt customif cmd cpp 中 发送数据的前提是进行主从配对连接 sdk给与了两种模式 IBRT SEARCH UI 未定义时我们可以自己定义主从蓝牙地址 IBRT SEARCH UI 定
  • 服务器系统能耗,服务器能耗怎么计算

    服务器能耗怎么计算 内容精选 换一换 DESS磁盘扩容成功后 需要在裸金属服务器的操作系统中对扩容部分的磁盘分配分区 已登录裸金属服务器 详细操作请参见 裸金属服务器用户指南 中章节 登录Windows裸金属服务器 已挂载磁盘至裸金属服务器
  • JS实现约瑟夫环

    传说罗马人占领了乔塔帕特 41 个犹太人被围堵在一个山洞里 他们拒绝被俘虏 而决定集体自杀 大家决定了一个自杀方案 41 个人围成一个圈 由第 1 个人开始顺时针报数 每报数为 3 的人立刻自杀 然后再由下一个人重新从 1 开始报数 依旧是
  • 笔记本电脑微信视频对方却听不到声音

    我真的是把网上的所有教程 试遍了都没弄好 我自己突发奇想要不然更新下 结果就成功了 首先可以先看看是不是微信版本的原因 麦克风出现问题了 右击我的电脑 gt 属性 gt 设备管理器 gt 音频输入和输出 gt 右击麦克风 gt 更新驱动程序
  • 数值分析Matlab二维正态(高斯)分布以及协方差矩阵

    数值分析Matlab二维正态 高斯 分布以及协方差矩阵 主要是使用了matlab的mvnrnd产生随机的正态 高斯 分布二维矩阵 然后绘制出来 代码运行结果生成的正态分布实验数据如图 MATLAB代码 mu1 0 0 sigma1 4 2
  • ACM输入输出

    写在前面 主要记录一下ACM输入输出的写法 一 输入数值 1 给定N的定长多行输入 题目 https ac nowcoder com acm contest 5657 B 代码 include
  • 【Java】基于朴素贝叶斯算法破解基于哈希表的随机字符替换加密算法

    Java 基于朴素贝叶斯算法破解基于哈希表的随机字符替换加密算法 不用看了 这篇文章是错的 得出的结果也不是正确的结果 我想错了 因为这个解密算法的前提是已经知道哈希表的情况下去计算的 而实际上应该是只靠统计去分析密文 所以实际破解所需要的