两个转子的转轮机原理详解与算法实现

2022-07-20 14:34:44 浏览数 (1)

【转轮机编写(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码表中从而完成了对应的输出转换。

初学信息安全,可能存在错误之处,还请各位不吝赐教。

受于文本原因,本文相关算法实现工程无法展示出来,现已将资源上传,可自行点击下方链接下载。

两转子的转轮机原理详解与代码实践工程文件

0 人点赞