通过Java实现恩尼格玛密码机

article/2025/10/2 9:21:33

1 简介  

      前一段时间看了B站介绍恩尼格玛密码机的视频,试了试用Java来实现一台恩尼格玛密码机,在此文章中来简单介绍自己实现的思路和代码以供大家学习参考,如有错误,欢迎指出。

        单表替换密码会由于字母分布的规律被破解出来,可以使用多表替换来增加破解难度,而恩尼格玛密码可以算是一种多表替换的加密方法。

        恩尼格玛密码机加密原理简单的来说就是每当输入一位明文的时候有规律地动态更换替换表。由于其结构独特的设计使恩尼格玛密码具有自反性和排己性。

2 原理介绍及代码

2.1 密码机模拟

        密码机包含一个输入部分,三个转子,一个反射板。由于其自反的特性,加密和解密的方法一致所以只有一个加密方法,还有一个设置三个转子位置的方法。

//一个恩尼格玛密码机由一个输入轮,三个转轮和一个反射板构成
public class EnigmaCoder {private InputWheel input;private Rotator r1,r2,r3;private Reflector ref;public EnigmaCoder(int num1,int num2,int num3) {Integer[] array = {1,24,25,9,10,11,12,4,19,20,21,26,0,5,6,7,8,22,23,15,16,13,14,2,3,17,18};List<Integer> list = new ArrayList<Integer>();Collections.addAll(list, array);input = new InputWheel();r1 = new Rotator(list,num1,1);r2 = new Rotator(list,num2,2);r3 = new Rotator(list,num3,3);ref = new Reflector();}String encode(String str) {String result = "";Character ch;int temp;for(int i = 0;i < str.length();i++) {ch = str.charAt(i);temp = ref.getNum(r3.getNum(r2.getNum(r1.getNum(input.inputChar(ch)))));temp = r1.getNumBack(r2.getNumBack(r3.getNumBack(temp)));ch = input.inputNum(temp);result += ch;}return result;}void setCoder(int num1,int num2,int num3) {r1.setPoint(num1);r2.setPoint(num2);r3.setPoint(num3);}
}

2.2 输入轮模拟

        明文一位一位从密码机传到输入轮中,输入轮将明文对应的下标,最终在转子中变换的是替换表的下标,也就是整形数。输入轮中包含两个方法,一个是文字转为对应下标的整形数,另一个是下标转文字。

public class InputWheel {final static int CHAR_NUMBER = 27;//26个字母和一个空格List<Character> link;public InputWheel() {Character[] str = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',' '};link = new ArrayList<Character>();Collections.addAll(link, str);}int inputChar(Character ch) {int num = -1;//默认为错误输出for(int i = 0;i < CHAR_NUMBER;i++) {if(ch.equals(link.get(i))) {num = i;break;}}return num;}Character inputNum(int num) {Character ch = '?';//默认为错误输出ch = link.get(num%CHAR_NUMBER);return ch;}
}

2.3 转子模拟

        转子由一个代表接线的整形数组,当前转子的指针和转子的序号(外圈转子转一圈内圈转子转一个刻度),该密码机为三个转子,每个转子的接线和初始位置都可以单独设置。由于需要有设置当前转子指针的功能,所有有get和set指针的两个方法。还有通过替代表输入和输出的两个方法。

        不同序号的转子判断的代码我是拿switch写的,如果需要拓展功能,可以用type进行计算,最终达到一样的效果,并且还能继续叠加转子。

public class Rotator {final static int CHAR_NUMBER = 27;//26个字母和一个空格private List<Integer> link;private List<Integer> rlink;private int count,point,type;public Rotator(List<Integer> link,int point,int type) {super();this.link = link;Integer[] array = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26};rlink = new ArrayList<Integer>();Collections.addAll(rlink, array);for(int i = 0; i < link.size(); i++) {rlink.set(link.get(i), i);}this.point = point;this.type = type;count = 0;}int getNum(int offset) {//所选数字为目前最低位的指针加上输入的偏移量count++;int sequence = offset + point; if(sequence >= CHAR_NUMBER) sequence = sequence%CHAR_NUMBER;//先加charnumber使之变为正数,再取其余数int num = (link.get(sequence) - point + CHAR_NUMBER)%CHAR_NUMBER;return num;}int getNumBack(int offset) {count++;int sequence = offset + point; if(sequence >= CHAR_NUMBER) sequence = sequence%CHAR_NUMBER;int num = (rlink.get(sequence) - point + CHAR_NUMBER)%CHAR_NUMBER;switch(type) {case 1: {//最低级转轮每次读取都转一次,字符进入后再出来共读取两次if(count%2 == 0) {point++;count = 0;}break;}case 2: {//最低轮转一圈第二轮转一刻if(count%CHAR_NUMBER == 0) {point++;count = 0;}break;}case 3: {if(count%(CHAR_NUMBER*CHAR_NUMBER) == 0) {point++;count = 0;}break;}default:{break;}}return num;}void setPoint(int point) {this.point = point;count = 0;}int getPoint() {return point;}
}

2.4 反射板模拟

        反射板只需要一个获得反射后下标的方法即可。需要注意的是反射板内部的link(替代表)和转子内部的不同,反射板的link需要正序的数组两两替换得到,转子则没有要求。

public class Reflector {final static int CHAR_NUMBER = 27;//26个字母和一个空格private List<Integer> link;public Reflector() {super();Integer[] array = {1,0,3,2,5,4,7,6,9,8,11,10,13,12,15,14,17,16,19,18,21,20,23,22,25,24,26};link = new ArrayList<Integer>();Collections.addAll(link, array);}int getNum(int i) {return link.get(i);}
}

3 结果演示及测试代码

 

public class Test {public Test() {EnigmaCoder coder = new EnigmaCoder(0,0,0);BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); //ctr + shift + otry {System.out.println("请输入需要加密的字符串:");String str = in.readLine();System.out.println("加密前为:"+str);str = coder.encode(str);System.out.println("加密后为:'"+str+"'");coder.setCoder(0, 0, 0);System.out.println("请输入需要解密的字符串:");str = in.readLine();str = coder.encode(str);System.out.println("解密后为:'"+str+"'");} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}public static void main(String[] args) {Test ts = new Test();}}

部分参考:https://www.bilibili.com/video/BV1DS4y1R7hM


http://chatgpt.dhexx.cn/article/3jqu8fwn.shtml

相关文章

加密解密工具 之 恩尼格玛密码机密码

工具链接&#xff1a;http://www.atoolbox.net/Tool.php?Id993 恩尼格码密码机及加密原理 恩尼格码密码机是二战时期的纳粹德国及其盟国&#xff0c;特别是德国军方所使用的一种高级机械加密系统&#xff0c;以转子结构为主体。 密码机一般装在一个盒子里。当要加密一串字符…

恩尼格玛密码机原理解析(Enigma principle )

恩尼格玛机也结合了机械系统与电子系统。机械系统包括了一个包含了字母与数字的键盘&#xff0c;相邻地排列在一个轴上的一系列名为“转子” 的旋转圆盘&#xff0c;还有一个在每次按键后就使一个或几个转子旋转的装置。各种恩尼格玛机上的机械系统都各为不同&#xff0c;但是&…

使用HttpClient模拟POST请求

HttpClient 是 Apache Jakarta Common 下的子项目&#xff0c;可以用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包&#xff0c;并且它支持 HTTP 协议最新的版本和建议。当前官网最新版介绍页是&#xff1a;http://hc.apache.org/httpcomponents-client-4…

fastmock模拟post、get请求

参考资料&#xff1a; fastmock 帮助文档 初学者可以根据这个文档了解如何创建项目 【前端必备基本技能】-fastMock平台使用_哔哩哔哩_bilibili 如果觉得文档不好理解的小伙伴可以看这个视频&#xff0c;本人觉得讲的很仔细。 Mock.js 实例练习&#xff1a; get请求 …

TCP模拟HTTP请求

HTTP的特性 HTTP是构建于TCP/IP协议之上&#xff0c;是应用层协议&#xff0c;默认端口号80 HTTP协议是无连接无状态的 HTTP报文 请求报文 HTTP协议是以ASCⅡ码传输&#xff0c;建立在TCP/IP协议之上的应用层规范。 HTTP请求报文由请求行&#xff08;request line&#xff09;、…

使用postman模拟post、get请求

postman通常作为一种接口测试工具&#xff0c;如&#xff1a;采用post、get等方式&#xff0c;模拟对接口进行访问&#xff0c;用于查看接口功能是否正常。 模拟POST请求 选择请求方式为POST 设置请求url地址 http://localhost:8081/webside/subSystemLogin.html 选择Header…

如何简单的模拟发送http post请求

有天在做项目演示的时候要用到post请求的模拟发送&#xff0c;为此总不至于写一个html页面&#xff0c;当时只记得百度了一下模拟发送http post请求&#xff0c;方法大概都是说用fiddler工具或者使用cmd内置telnet客户端模拟http请求。 这里抄送附上fiddler工具和telnet模拟po…

接口测试中模拟post四种请求数据

转自 作者&#xff1a;隋胖胖LoveFat 链接&#xff1a;https://www.jianshu.com/p/3b6d7aa2043a 来源&#xff1a;简书 一、背景介绍 在日常的接口测试工作中&#xff0c;模拟接口请求通常有两种方法&#xff0c;fiddler模拟和HttpClient模拟。 Fiddler是一个简单的http协议调…

谷歌学术访问

https://via.hypothes.is/ 不需要镜像&#xff0c;不需要任何操作&#xff0c;只需打开这个网站&#xff0c;输入你要访问的学术网站&#xff0c;秒开 第一步&#xff1a; 第二步:

谷歌学术(google scholar)个人主页的论文信息不准确怎么办?

题目&#xff1a;谷歌学术(google scholar)个人主页的论文信息不准确怎么办&#xff1f; 谷歌学术主页是很多人展示自己学术成果的一种方式&#xff0c;但很多时候&#xff0c;谷歌自动给你聚集到主页的论文信息是有误的&#xff0c;这时候怎么去编辑呢&#xff1f; 论文信息…

谷歌学术介绍

转载自&#xff1a;http://blog.renren.com/share/111541487/15517062888 “谷歌学术”是谷歌搜索引擎中的学术检索部分&#xff0c;相对于知网、维普、万方、Pubmed等专业的论文数据库来说功能单薄了些&#xff0c;但具有页面简约、搜索速度快、集国内外文献于一体、某些文章可…

Google 学术搜索(Google Scholar)使用技巧

本文简介Google 学术搜索&#xff08;Google Scholar&#xff09;使用技巧&#xff0c; 关于Web Of Science 上搜索文献&#xff0c;查看SCI分区及影响因子情况参见我的另一篇博客&#xff08;https://xiongyiming.blog.csdn.net/article/details/78474211&#xff09; Google…

【谷歌学术】使用指南

【谷歌学术】使用指南 谷歌可以清楚看到作者的影响力&#xff0c;尤其是在衡量一个学者有多厉害&#xff0c;论文质量有多高【往往是博士阶层往上】 谷歌学术网站&#xff1a; https://scholar.google.com.hk/?hlzh-CN 查人 查论文都很好用 同时你订阅这个作者 还会收到他…

如何在谷歌学术下载论文

如何在谷歌学术下载论文&#xff08;在Mac Pro上记录&#xff0c;但是windows应该同样适用&#xff09; 1 下载谷歌浏览器 下载谷歌浏览器 官网截图如下&#xff1a; 2 下载谷歌浏览器扩展程序 googlehelper下载 在下载的时候&#xff0c;要记住下载的位置&#xff0c;后面…

谷歌学术搜索

Google Scholar &#xff08;谷歌学术搜索&#xff0c;简称GS&#xff09;是一个可以免费搜索学术文章的网络搜索引擎索引了出版文章中文字的格式和科目&#xff0c;能够帮助用户查找包括期刊论文、学位论文、书籍、预印本、文摘和技术报告在内的学术文献&#xff0c;内容涵盖自…

谷歌学术Google Scholar超实用干货(拒绝翻墙/插件)

最近看了很多大佬博主发的谷歌学术使用总结,觉得特别有用,小P在这里简单的总结一下,给自己做个使用大纲,也分享给大家啦!(觉得有帮助别忘了点赞、收藏哦) 谷歌学术简单来说就是一个汇集大量外文文献的网站(类似于百度学术)。百度学术的特点是:精简、不全不新,谷歌学…

科研——谷歌学术使用方法

输入需要搜索的文章名 点击“引用”&#xff0c;即可以出此篇文章的引用格式。点击“被引用次数”&#xff0c;即可以看到引用此篇文章的其他文章。 勾选“在引用文章中搜索”&#xff0c;在上方的空白处&#xff0c;搜索这些引用文章中的具体文章。 点击一篇查看是否被真正引用…

谷歌学术——下载论文

一些同学在找论文的时候&#xff0c;在学校数据库找不到&#xff0c;因此可以使用谷歌学术来找。但是国内被墙了&#xff0c;无法访问&#xff0c;所以可以使用镜像服务器。 首先进入谷歌镜像&#xff1a; 镜像网站&#xff08;https://ac.scmor.com/&#xff09; 点击进入之后…

国内外常用学术网站(访问不了“谷歌学术”的,试一试有惊喜哦)

搞学术的可能对如何能够快速查找优质免费学术资源感到头大于是笔者寻找了许许多多方法&#xff0c;搜集了很多网站&#xff0c;期望谷歌访问不了是可以找到替代或者与谷歌学术相媲美的网站&#xff0c;现汇总如下分享给大家&#xff0c;希望对搞研究的有所帮助。 一、学术网站…

RPC框架介绍

什么是RPC框架&#xff1a; 远程过程调用RPC&#xff0c;就是客户端基于某种传输协议通过网络向服务提供端请求服务处理&#xff0c;然后获取返回数据(对于ONE WAY模式则不返还响应结果)&#xff1b;而这种调用对于客户端而言&#xff0c;和调用本地服务一样方便&#xff0c;开…