【转轮机编写(2个转子)】
1. Equipment
(1) operating system version :WIN 10
(2) CPU instruction set: x 64
(3) software :Visual Studio 2019
2. process
- Problem background analysis
转轮机编写(2个转子)
首先了解关于Rotor Machines的概念,转轮机由一个键盘和一系列转轮组成,每个转轮是26个字母的任意组合。转轮被齿轮连接起来,当一个转轮转动时,可以将一个字母转换成另一个字母。照此传递下去,当最后一个转轮处理完毕时,就可以得到加密后的字母。还有一个经典的实例——Enigma-machine。
通常的转轮机是有三个转子,这里我仿照着上关于Enigma-machine的模型,我采用C 写了两个转子的转轮机。
- Solution
code:
代码语言:javascript复制#include<iostream>
#include<stdlib.h>
#include<string>
using namespace std;
/*
* @Author:timerring
* @Date: 2021-10-23 11:02:59
* @LastEditTime: 2021-10-26 13:09:06
* @FilePath:c:UserstimerringEnigma.cpp
*/
void TurnWheel(int* wheel_l, int* wheel_r);//加密时进行正向转动TurnWheel函数
void ReverseWheel(int* wheel_l, int* wheel_r);//解密时进行逆向转动ReverseWheel函数
void Encrypt(char* plaintext, char* ciphertext, int* slow_l, int* slow_r, int* fast_l, int* fast_r);//声明加密函数
void Decrypt(char* ciphertext, char* plaintext, int* slow_l, int* slow_r, int* fast_l, int* fast_r);//声明解密函数
void TurnWheel(int* wheel_l, int* wheel_r)
{//定义正向转轮函数
int temp = wheel_l[25];
//定义0-25共26个字母
//采用for循环依次复制完成左侧转轮操作
for (int i = 25; i > 0; i--)
//规定正向转轮是递减的方向
wheel_l[i] = wheel_l[i - 1];
wheel_l[0] = temp;
//同理完成右侧转轮操作
temp = wheel_r[25];
for (int i = 25; i > 0; i--)
wheel_r[i] = wheel_r[i - 1];
wheel_r[0] = temp;
}
void ReverseWheel(int* wheel_l, int* wheel_r)
{//定义逆向转轮函数
int temp = wheel_l[0];
for (int i = 0; i < 25; i )
//规定逆向转轮是递增的方向
wheel_l[i] = wheel_l[i 1];
wheel_l[25] = temp;
temp = wheel_r[0];
for (int i = 0; i < 25; i )
wheel_r[i] = wheel_r[i 1];
wheel_r[25] = temp;
}
void Encrypt(char* plaintext, char* ciphertext, int* slow_l, int* slow_r, int* fast_l, int* fast_r)
{
int count = 0;//快轮转动次数
for (unsigned int i = 0; i < strlen(plaintext); i )
{//加密过程
if ('A' <= plaintext[i] && plaintext[i] <= 'Z')
{//判断输入是否合法
int current = plaintext[i] - 'A';
//确定位置
current = slow_l[current];
for (int j = 0; j < 26; j )
{
if (current == slow_r[j])
{
current = fast_l[j];
break;
}
}
for (int j = 0; j < 26; j )
{
if (current == fast_r[j])
{
current = j;
break;
}
}
//转换到对应的大写字母ASCII码表中
ciphertext[i] = char(current 65);
count ;
TurnWheel(fast_l, fast_r);//快轮转动一次
if (count % 26 == 0)
{//判断是否需要正向转轮
TurnWheel(slow_l, slow_r);
}
}
}
}
void Decrypt(char* ciphertext, char* plaintext, int* slow_l, int* slow_r, int* fast_l, int* fast_r)
{//定义解密函数
int count = 0;
for (unsigned int i = 0; i < strlen(ciphertext); i )
{//先让轮子转成加密后的状态
if ('A' <= ciphertext[i] && ciphertext[i] <= 'Z')
{//判断输入是否合法
count ;
TurnWheel(fast_l, fast_r);
}
}
if (count % 26 == 0)
{
TurnWheel(slow_l, slow_r);
}
for (int i = strlen(ciphertext) - 1; i >= 0; i--)
{//解密过程
if ('A' <= ciphertext[i] && ciphertext[i] <= 'Z')
{//快轮先转回去一次再解密
ReverseWheel(fast_l, fast_r);
int current = ciphertext[i] - 'A';
current = fast_r[current];
for (int j = 0; j < 26; j )
{
if (current == fast_l[j])
{
current = slow_r[j];
break;
}
}
for (int j = 0; j < 26; j )
{
if (current == slow_l[j])
{
current = j;
break;
}
}
if (count % 26 == 0)
{
ReverseWheel(slow_l, slow_r);
}
count--;//判断结束再进行自减操作
//转换到对应的大写字母ASCII码表中
plaintext[i] = char(current 65);
}
}
}
int main()
{
int a;
while (true) {
cout << "You are welcome to use the two rotor Enigma-machine in SDUn" << endl;
cout << "Please enter the corresponding operation number:n1.Encryptt2.Decrypt" << endl;
cin >> a;
//定义快慢两个转子的初始状态
int slow_l[26] = { 24,25,26,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23 };
int slow_r[26] = { 21,3,15,1,19,10,14,26,20,8,16,7,22,4,11,5,17,9,12,23,18,2,25,6,24,13 };
int fast_l[26] = { 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 };
int fast_r[26] = { 8,18,26,17,20,22,10,3,13,11,4,23,5,24,9,12,25,16,19,6,15,21,2,7,1,14 };
char* plaintext = new char[128];
char* ciphertext = new char[128];
memset(plaintext, 0, 128);//初始化明文
memset(ciphertext, 0, 128);//初始化密文
switch (a)
{//根据tag的值来执行相应的操作
case 1:
cout << "Please input the string you want to entrypt:" << endl;
cin >> plaintext;
//加密过程
Encrypt(plaintext, ciphertext, slow_l, slow_r, fast_l, fast_r);
cout << "cipertext:" << endl;
for (unsigned int i = 0; i < strlen(ciphertext); i )
{//按位输出密文
cout << ciphertext[i];
}
cout << endl;
break;
case 2:
cout << "Please input the string you want to decrypt:" << endl;
cin >> ciphertext;
//解密过程
Decrypt(ciphertext, plaintext, slow_l, slow_r, fast_l, fast_r);
cout << "cleartext:" << endl;
for (unsigned int i = 0; i < strlen(plaintext); i )
{//按位输出明文
cout << plaintext[i];
}
cout << endl;
break;
default:
system("cls");
break;
}
}
return 0;
}
Test sample:
此处测试样例明文为SDUQD,并将输出的加密结果再进行解密,得到解密后的明文仍为SDUQD,可知转轮机程序正常运行。
3. summary and harvest
我在实践上对于传统密码学,尤其是借助不同形式而实现的多表代换密码应用有了全新的认识,转轮密码机由多个转轮构成,每个转轮旋转的速度都不一样,这次我写的程序是2个转子,分别标号为1,2,其中1号转轮转动26个字母后,2号转轮就转动一个字母。因此,当转轮密码机转动26X26次后,所有转轮恢复到初始状态,即2个转轮密码机的一个周期长度为26X26(676)的多表代换密码。
在编写密码机的过程中,我按照密码机的代换原理,分别整个过程中可能用到的函数,其中的加密时采用的TurnWheel正向转轮以及解密时采用的ReverseWheel在最开始没有思路,因为不知道采用什么方式能完成一个动态的转轮过程,后来想到了数据结构与算法中的冒泡排序,采用了数组元素交换的方式完成动态的排序,于是采用相同的思路,我规定了中间变量,并且设定正向转轮时按照递减的方向依次顺序复制的方法实现。在最后进行明文输出的时候输出了乱码,通过分析,我注意到忘了将current变量在输出时转换到对应的大写字母ASCII码表中,于是通过序号 65转到ASCII码表中从而完成了对应的输出转换。
初学信息安全,可能存在错误之处,还请各位不吝赐教。
受于文本原因,本文相关算法实现工程无法展示出来,现已将资源上传,可自行点击下方链接下载。
两转子的转轮机原理详解与代码实践工程文件