最近朋友突然给我发了一个二战时期德国使用的加密机器恩尼格玛机的加密原理。个人看了感觉很有意思,于是便琢磨了起来。由于我是java的初学者,想使用这样的逻辑原理熟悉一下java语言的使用,便编写了以下的代码用来实现。
程序设计
我最初是想自己琢磨出恩尼格玛机在java中的实现的(因为第一感觉不难),但是奈何学习java还没多久,没有大佬们使用得如鱼得水。所以就查阅了许多资料,将密码机的各个部分分了几类实现密码机各个部分的功能。
我们首先来看密码机如何运作的,简单来说就是用户输入一串英文字符,然后这些字符首先逐一交给插线板进行反射处理;之后反射器又将经过处理的字符交给转子进行加密。转子完成第一轮加密输出到最后一个转子末端的时候通过反射器进行反射;反射的值再次进入转子进行反向二次加密。最后由反射器输出的值输入到插线板进行字母替换后输出最终的结果。
因此我们可以粗略将流程规范为:输入-->插线板-->各级转子-->反射器-->各级转子-->插线板-->输出
程序实现
反射器类(Reflector类)
package Enigma;
public class Reflector {
private String codeSet;
//初始化反射器替换编码
public Reflector(String codeSet) {
super();
this.codeSet = codeSet;
}
//反射器替换操作
public char reflect(char c) {
int index=c-'A';
return codeSet.charAt(index);
}
}
转子类(Rotor类)
package Enigma;
public class Rotor {
private String codedSet;//转子编码集
private int position;//转子位置
//初始化转子属性
public Rotor(String codedSet, int location) {
super();
this.codedSet = codedSet;
this.position = location;
}
//正向加密方法
public char forwardEncryption(char input) {
int index=input-'A'+position;
if(index>26)
index%=26;
return codedSet.charAt(index);
}
//反向加密方法
public char reverseEncryption(char input) {
int index=codedSet.indexOf(input)-position;
if(index<0)
index+=26;
return (char)(index+'A');
}
//转子转动方法
public void rotateRotor() {
this.position=(this.position+1)%26;
}
//获得转子位置方法
public int getPosition() {
return position;
}
}
插线板类(Plugbord类)
package Enigma;
import java.util.HashMap;
import java.util.Map;
public class Plugboard {
private Map<Character,Character> cm=new HashMap<>();
//初始化插线板替换编码(为了替换方便我选择了HashMap,个人认为这样可以提高查询效率)
public Plugboard(String str) {
super();
for(int i=0;i<str.length();i+=2) {
char a=str.charAt(i);
char b=str.charAt(i+1);
cm.put(a, b);
cm.put(b, a);
}
}
//输出替换
public char switchCharacter(char input) {
return cm.getOrDefault(input,input);
}
}
加密类(Encrypt类)
package Enigma;
public class Encrypt {
private Rotor rotor[];
private Reflector reflector;
private Plugboard plugboard;
public Encrypt(Rotor[] rotor, Reflector reflector, Plugboard plugboard) {
super();
this.rotor = rotor;
this.reflector = reflector;
this.plugboard = plugboard;
}
public String encrypt(String message) {
StringBuffer strM=new StringBuffer();
for(char c:message.toCharArray()) {
if(Character.isLetter(c)) {
c=Character.toUpperCase(c);
c=this.plugboard.switchCharacter(c);
//通过转子正向加密
for(Rotor r:rotor) {
c=r.forwardEncryption(c);
}
//通过反射器
c=reflector.reflect(c);
//进行反向加密
for(int i=rotor.length-1;i>=0;i--) {
c=rotor[i].reverseEncryption(c);
}
//通过插线板
c=plugboard.switchCharacter(c);
}
strM.append(c);
}
return strM.toString();
}
//转子依次转动逻辑(按照前一个转子转动一圈后一个转子转动一下来写)
public void rotateRotors() {
boolean rotateNext=true;
for(int i=0;i<rotor.length;i++) {
if(rotateNext) {
rotor[i].rotateRotor();
rotateNext=(rotor[i].getPosition()==0);
}else {
break;
}
}
}
}
之后就可以在Main函数里实例化加密类对象和初始化各个部件的信息啦!
Main类
package Enigma;
import java.util.Scanner;
public class Main {
public static void main(String[] args){
// TODO Auto-generated method stub
//初始化各个零件的编码表和转子的初始位置
Rotor rotor1 = new Rotor("EKMFLGDQVZNTOWYHXUSPAIBRCJ", 0);
Rotor rotor2 = new Rotor("AJDKSIRUXBLHWTMCQGZNPYFVOE", 5);
Rotor rotor3 = new Rotor("BDFHJLCPRTXVZNYEIWGAKMUSQO", 24);
Reflector reflector = new Reflector("YRUHQSLDPXNGOKMIEBFZCWVJAT");
Plugboard plugboard = new Plugboard("AZBYCXDWEVFUGTHSIRJQ");
//创建加密类进行加密操作
Encrypt enigmaMachine = new Encrypt(new Rotor[]{rotor1, rotor2, rotor3}, reflector, plugboard);
Scanner cin=new Scanner(System.in);
String encryptedMessage = enigmaMachine.encrypt(cin.next());
cin.close();
System.out.println("Encrypted Message: " + encryptedMessage);
}
}
总结
密码机的原理我是看b站视频了解到的,在此如果大家感兴趣的话也可以看这个up主分享的视频,讲的很全面的: https://www.bilibili.com/video/BV1TN4y1J7dq/?share_source=copy_web&vd_source=64f6cad256b7a8881c7b8f651e3080f9
写恩尼格玛机的操作并不复杂,其实还蛮好玩的,从中也能学到许多东西。我发布这篇博客也是希望热爱密码学的初学者们能够在网上找到更多实例帮助自己学习理解密码学和编程。我自己也是一个小白,也在努力学习,希望大家和我都能够在日后努力学习,更加进步啦!