自己打造一台恩尼格码密码机【转译】手工电子DIY教程

自己打造一台恩尼格码密码机【转译】

这个作品是2013年无线电单片机竞赛的亚军。感谢所有支持这个作品的你们!

在对称加密学当中,恩尼格码机绝对是承前启后的存在。它将密码学研究从以前的语言文字学中心完全转移到了数学身上。在这里牵涉的密码并不是我们平时邮箱、银行帐号那种狭义概念,那种顶多叫做口令。这里说的密码就是通过某种转换规律方式,把一篇文章变得面目全非,非常人能阅读,以达到保密效果。这篇文章适于电脑控、军事控、历史控、数学控阅读,请做好烧脑准备。【原址:】

主要材料:

  1个Arduino Mega 2560板  26个字母按键
  26个1/4英寸单通道母接口  10个1/4英寸单通道公接口
  36个机械按钮  1个单刀三掷开关
  4个16段橙色LED显示  4个注塑2升汽水瓶罩子
  1个胶合板盒子  一个铰链
  一个半榫接锁  一个接线盘
  38个470欧电阻  40个1千欧电阻
  7个IRF9Z24N P型晶体管  1块金属片

所需工具:

  以及喷漆

制作步骤:

第1步:

自己打造一台恩尼格码密码机【转译】 第2张

在对称加密学当中,恩尼格码机绝对是承前启后的存在。它将密码学研究从以前的语言文字学中心完全转移到了数学身上。在这里牵涉的密码并不是我们平时邮箱、银行帐号那种狭义概念,那种顶多叫做口令。这里说的密码就是通过某种转换规律方式,把一篇文章变得面目全非,非常人能阅读,以达到保密效果。这篇文章适于电脑控、军事控、历史控、数学控阅读,请做好烧脑准备。

这是我们的初号机。以下教程将手把手教你如何完美山寨史上著名的德国恩尼格玛密码机(以下称哑谜机,不清楚历史的可以到维基、百度等地方脑补一下)。这个基于Arduino的开源程序能够加解密任何哑谜机M4型(海军型)的信息。

这个第一台全功能开源完美哑谜机复制品是根据sketchsk3tch写的《Kid’s Game to Arduino Enigma Machine》(从儿童玩具到Arduino恩尼格玛机)所作。

采用多路复用LED电路,仅用38个针脚的115个发光二极管和4个针脚的36个按键所连接的整个电路,全靠在键盘回路里准确放置的电阻以及P型号晶体管得以实现。要不然,4个16段显示器,以及每个按键上的LED将大幅增加所需针脚总量,即使用了Arduino Mega板但如果没用上述两个方法也不能如此简洁。 面对电路的超额需求,我们在设计了专用的PCB板。直接跳到第10步和以后的步骤可以找到更多信息。同时,我们以测试过的完整电子组装套装发布。

第2步:

自己打造一台恩尼格码密码机【转译】 第3张

面包板上的论证

第3步:

自己打造一台恩尼格码密码机【转译】 第4张

在开始制作电子哑谜机之前,我们先要确保能驱动16段LED显示。如果能的话,我们就能做接下来的所有步骤,除了数学上的问题,一切都是浮云。

第4步:

自己打造一台恩尼格码密码机【转译】 第5张

万事具备

第5步:

自己打造一台恩尼格码密码机【转译】 第6张

布置零件

第6步:

自己打造一台恩尼格码密码机【转译】 第7张

第7步:

自己打造一台恩尼格码密码机【转译】 第8张

第8步:

自己打造一台恩尼格码密码机【转译】 第9张

第9步:

自己打造一台恩尼格码密码机【转译】 第10张

6*8寸无线电面包版是最合适放置所有元件的,既不多余也不拥挤,而且和哑谜机盒子内部完美吻合。

最初我们将面包等分三块区域,但很快意识到如此一来,电子版哑谜机将比原版机械哑谜机长。于是我们将所有零件缩放到正好够占用的空间。

每个元件位置就绪,下一步就是焊接。

第10步:

自己打造一台恩尼格码密码机【转译】 第11张

第11步:

自己打造一台恩尼格码密码机【转译】 第12张

我焊,我焊,我焊焊焊……

第12步:

自己打造一台恩尼格码密码机【转译】 第13张

第13步:

自己打造一台恩尼格码密码机【转译】 第14张

第14步:

自己打造一台恩尼格码密码机【转译】 第15张

第15步:

自己打造一台恩尼格码密码机【转译】 第16张

第16步:

自己打造一台恩尼格码密码机【转译】 第17张

好吧,在单一作品身上,我从没焊接如此多次。16段显示的18个针脚,还有26个字母键乘以每个4个脚,外加26个键盘灯,一些其他LED,一个三掷开关,真乃“成吉思焊”。

当初我们的决定是使这些16段LED显示看起来像老式电子管的感觉,增加了不少焊点,“巨焊”!

Arduino Mega板上针脚的分配: 17段:

第17步:

自己打造一台恩尼格码密码机【转译】 第18张

第18步:

自己打造一台恩尼格码密码机【转译】 第19张

第19步:

自己打造一台恩尼格码密码机【转译】 第20张

在原版M4型木盒内得到确定位置数据后,我们买了一块胶合板,将它切块,然后砌盒子。

我们从旧服务器机架上卸了一块钢板,厚度正合需要。将模具(上面早已画好每个按键和灯位,并切好了洞洞)盖在钢板上,然后用记号笔画出需要切出的洞洞。

接着,我们用喷漆把它涂黑,就像真的哑谜机那样。

第20步:

自己打造一台恩尼格码密码机【转译】 第21张

组装测试

第21步:

自己打造一台恩尼格码密码机【转译】 第22张

第22步:

自己打造一台恩尼格码密码机【转译】 第23张

第23步:

自己打造一台恩尼格码密码机【转译】 第24张

第24步:

自己打造一台恩尼格码密码机【转译】 第25张

第25步:

自己打造一台恩尼格码密码机【转译】 第26张

第26步:

自己打造一台恩尼格码密码机【转译】 第27张

首先把金属板在面包版上永久固定,确保所有按键正常工作,所有LED都能发光。

接着就是把这一大坨东东装入木盒,确保没有空隙位置。

第27步:

自己打造一台恩尼格码密码机【转译】 第28张

第28步:

自己打造一台恩尼格码密码机【转译】 第29张

在组装硬件过程中,我们也写了个小型Arduino程序框架,用以测试特定几个需要关注的部分:

用来测试每个按键信号能准确读取,还有测试10个功能按键的代码。

Enigma_POST(上电自检)确保在每种模式下所有键盘等都能准确亮起,在每种模式下每个LED信号都能传送。我们对原本面包板上的代码做了修正,确保4个16段LED显示的每个部件无懈可击。

但,即使所有手上的程序片段都说明机器状态完好,重现M4海军型哑谜机加解密功能,数学方面居功至伟。

所有Arduino程序片段在我们刚刚建好的云端都能找到。

以下是Enigma_POST程序片段(上电自检):

/* Enigma Development Code to Test each of the 4 Nixies, the 5 LEDs,
then Turn On each Lamp in sequence.
Written by Marc Tessier & James Sanderson 9/8/13
*/

// Define the 16-Segments Pins
int segment[17] = {24,22,25,31,38,36,32,30,28,26,23,27,33,35,34,29,37};
int anode[4] = {39,41,43,45};

// Define the 9 lamps Pins
int lamp[9] = {10,9,8,7,6,5,4,3,2};
int lanode[3] = {11,12,13};

// LTP587P Segments: A,B,C,D,E,F,G,H,K,M,N,P,R,S,T,U,dp
boolean segmentvals[39][17] = { { 0,0,0,0,1,1,0,0,1,1,1,0,1,1,1,0,1 }, // = A
{ 0,0,0,0,0,0,1,1,1,0,1,0,1,0,1,1,1 }, // = B
{ 0,0,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1 }, // = C
{ 0,0,0,0,0,0,1,1,1,0,1,1,1,0,1,1,1 }, // = D
{ 0,0,1,1,0,0,0,0,1,1,1,0,1,1,1,0,1 }, // = E
{ 0,0,1,1,1,1,0,0,1,1,1,0,1,1,1,0,1 }, // = F
{ 0,0,1,0,0,0,0,0,1,1,1,0,1,1,1,1,1 }, // = G
{ 1,1,0,0,1,1,0,0,1,1,1,0,1,1,1,0,1 }, // = H
{ 0,0,1,1,0,0,1,1,1,0,1,1,1,0,1,1,1 }, // = I
{ 1,1,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1 }, // = J
{ 1,1,1,1,1,1,0,0,1,1,0,1,0,1,1,0,1 }, // = K
{ 1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1 }, // = L
{ 1,1,0,0,1,1,0,0,0,1,0,1,1,1,1,1,1 }, // = M
{ 1,1,0,0,1,1,0,0,0,1,1,1,0,1,1,1,1 }, // = N
{ 0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1 }, // = O
{ 0,0,0,1,1,1,0,0,1,1,1,0,1,1,1,0,1 }, // = P
{ 0,0,0,0,0,0,0,0,1,1,1,1,0,1,1,1,1 }, // = Q
{ 0,0,0,1,1,1,0,0,1,1,1,0,0,1,1,0,1 }, // = R
{ 0,0,1,0,0,0,1,0,1,1,1,0,1,1,1,0,1 }, // = S
{ 0,0,1,1,1,1,1,1,1,0,1,1,1,0,1,1,1 }, // = T
{ 1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1 }, // = U
{ 1,1,1,1,1,1,0,0,1,1,0,1,1,1,0,1,1 }, // = V
{ 1,1,0,0,1,1,0,0,1,1,1,1,0,1,0,1,1 }, // = W
{ 1,1,1,1,1,1,1,1,0,1,0,1,0,1,0,1,1 }, // = X
{ 1,1,1,1,1,1,1,1,0,1,0,1,1,0,1,1,1 }, // = Y
{ 0,0,1,1,0,0,1,1,1,1,0,1,1,1,0,1,1 }, // = Z
{ 0,0,0,0,0,0,0,0,1,1,0,1,1,1,0,1,1 }, // = 0
{ 1,1,0,0,1,1,1,1,1,1,0,1,1,1,1,1,1 }, // = 1
{ 0,0,0,1,0,0,0,1,1,1,1,0,1,1,1,0,1 }, // = 2
{ 0,0,0,0,0,0,1,1,1,1,1,0,1,1,1,1,1 }, // = 3
{ 1,1,0,0,1,1,1,0,1,1,1,0,1,1,1,0,1 }, // = 4
{ 0,0,1,0,0,0,1,0,1,1,1,0,1,1,1,0,1 }, // = 5
{ 0,0,1,0,0,0,0,0,1,1,1,0,1,1,1,0,1 }, // = 6
{ 0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1 }, // = 7
{ 0,0,0,0,0,0,0,0,1,1,1,0,1,1,1,0,1 }, // = 8
{ 0,0,0,0,0,0,1,0,1,1,1,0,1,1,1,0,1 }, // = 9
{ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 }, // = Space
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, // = Full Lit
{ 1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1 } // = SS
};
// LTP587P Segments: A,B,C,D,E,F,G,H,K,M,N,P,R,S,T,U,dp

boolean lampvals[9][9] = { { 0,1,1,1,1,1,1,1,1 }, // = Q or A or P
{ 1,0,1,1,1,1,1,1,1 }, // = W or S or Y
{ 1,1,0,1,1,1,1,1,1 }, // = E or D or X
{ 1,1,1,0,1,1,1,1,1 }, // = R or F or C
{ 1,1,1,1,0,1,1,1,1 }, // = T or G or V
{ 1,1,1,1,1,0,1,1,1 }, // = Z or H or B
{ 1,1,1,1,1,1,0,1,1 }, // = U or J or N
{ 1,1,1,1,1,1,1,0,1 }, // = I or K or M
{ 1,1,1,1,1,1,1,1,0 } // = O or L
};

int value_row1 = 0;
int value_row2 = 0;
int value_row3 = 0;
char key = 91;

int led1 = 40;
int led2 = 42;
int led3 = 44;
int led4 = 46;
int led5 = 48;
int wait = 100;



void setup() {
for (int index = 0 ; index <= 3; index++) {
pinMode (anode[index], OUTPUT);
digitalWrite (anode[index], 1);
}
for (int index = 0 ; index <= 16; index++) {
pinMode (segment[index], OUTPUT);
digitalWrite (segment[index], 1);
}
// initialize the digital pins as an output.
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);
pinMode(led4, OUTPUT);
pinMode(led5, OUTPUT);
for (int index = 0 ; index <= 2; index++) {
pinMode (lanode[index], OUTPUT);
digitalWrite (lanode[index], 1);
}
for (int index = 0 ; index <= 8; index++) {
pinMode (lamp[index], OUTPUT);
digitalWrite (lamp[index], 1);
}
}

void loop() {
sixteenSegWrite(0, 38);
sixteenSegWrite(1, 38);
sixteenSegWrite(2, 38);
sixteenSegWrite(3, 38);

digitalWrite(led1, HIGH); // turn the LED on (HIGH is the voltage level)
delay(200); // wait for a second
digitalWrite(led1, LOW); // turn the LED off by making the voltage LOW
delay(wait); // wait for a second
digitalWrite(led2, HIGH); // turn the LED on (HIGH is the voltage level)
delay(200); // wait for a second
digitalWrite(led2, LOW); // turn the LED off by making the voltage LOW
delay(wait); // wait for a second
digitalWrite(led3, HIGH); // turn the LED on (HIGH is the voltage level)
delay(200); // wait for a second
digitalWrite(led3, LOW); // turn the LED off by making the voltage LOW
delay(wait); // wait for a second
digitalWrite(led4, HIGH); // turn the LED on (HIGH is the voltage level)
delay(200); // wait for a second
digitalWrite(led4, LOW); // turn the LED off by making the voltage LOW
delay(wait); // wait for a second
digitalWrite(led5, HIGH); // turn the LED on (HIGH is the voltage level)
delay(200); // wait for a second
digitalWrite(led5, LOW); // turn the LED off by making the voltage LOW
delay(wait); // wait for a second

for (int index = 0 ; index <= 2; index++) {
digitalWrite (lanode[index], 0);
for (int mychar = 0; mychar < 9; mychar++) {
for (int sindex = 0; sindex < 9; sindex++) {
digitalWrite(lamp[sindex], lampvals[mychar][sindex]);
delay (30);
}
}
digitalWrite (lanode[index], 1);
}
}

void sixteenSegWrite(int digit, int character) {
digitalWrite(anode[digit],0);
for (int index = 0; index < 17; index++) {
digitalWrite(segment[index], segmentvals[character][index]);
}
}

第29步:

自己打造一台恩尼格码密码机【转译】 第30张

第30步:

自己打造一台恩尼格码密码机【转译】 第31张

第31步:

自己打造一台恩尼格码密码机【转译】 第32张

第32步:

自己打造一台恩尼格码密码机【转译】 第33张

第33步:

自己打造一台恩尼格码密码机【转译】 第34张

第34步:

自己打造一台恩尼格码密码机【转译】 第35张

第35步:

自己打造一台恩尼格码密码机【转译】 第36张

第36步:

自己打造一台恩尼格码密码机【转译】 第37张

第37步:

自己打造一台恩尼格码密码机【转译】 第38张

首先,我们写了个函数,给每个哑谜机工作模式用。

在模式0、默认模式,哑谜机仅仅是一台普通打字机,以跑马灯方式显示它的型号。

模式1下,允许用户从八个转子中选取三个,两个反射器中选择一个进行使用。

模式2下,允许用户排列转子次序。

模式3用于自定义转子初始字母排列。

选择模式4,用户最多可以使用接线板上10对交换字母排列。

模式5是运行模式,此时哑谜机能加解密任何从键盘录入的信息。

如果有足够利润,我们将研发印刷电路板,装载更容易组装的全功能哑谜机复制品。

第38步:

自己打造一台恩尼格码密码机【转译】 第39张

电路图

第39步:

自己打造一台恩尼格码密码机【转译】 第40张

徇众要求,电路图两份在此。

第一个是仿电子管(4个16段显示单元)如何布线,用于显示转子在哑谜机上的输出信号。同时,它们也用于每种调试模式,反馈用户机器设定信息。

第二幅电路图显示26个字母按键及10个功能键、26个键盘灯和5个LED是如何布线的。

所有LED电阻都是470欧,而开关电阻则都是1千欧。 印刷电路设计档仍在修正中。 希望您享受我们第一份制作教程,感谢您抽出宝贵时间阅读!

第40步:

自己打造一台恩尼格码密码机【转译】 第41张

PCB样机版

第41步:

自己打造一台恩尼格码密码机【转译】 第42张

徇众要求,我们设计及定制了一些印刷电路板。

它们终于面世了,如此清纯可爱!我们忙于组装,并测试其中一块样品,确保它在功能上与外观一样完美无暇。更重要的是,能和那台原型测试机一样的功能。 订购回来的底板几乎完美,只需一点引脚线去修补设计瑕疵。而这些瑕疵对功能没有影响,修理它们是小菜一碟。 有了这些引脚,你能更容易制作自己的哑谜复刻机,比起教程里的布线方便多了。我们在此很高兴宣布,测试完成,新型板一样给力!

第42步:

自己打造一台恩尼格码密码机【转译】 第43张

组装完成的作品

第43步:

自己打造一台恩尼格码密码机【转译】 第44张

第44步:

自己打造一台恩尼格码密码机【转译】 第45张

第45步:

自己打造一台恩尼格码密码机【转译】 第46张

第46步:

自己打造一台恩尼格码密码机【转译】 第47张

第47步:

自己打造一台恩尼格码密码机【转译】 第48张

花了一晚上组装完成

小贴士:

原址: