PTA-Advanced Enigma Cracking(enigma破解)

Advanced Enigma Cracking

题目要求

本题目需要模拟当年破解Enigma的过程,现在我们已经知道Plugboard, RingSetting, CipherText 和 Word

已知 PlainText 中一定包含单词 Word, 求破解 MessageKey, PlainText 和 RotorNum

由于完全破解耗时太长,输入还会给出3个齿轮中最左侧那个齿轮的编号。

提示

建议你实现一个加密/解密函数 与MyEnigma.exe 产生的结果相对比 完全一致后再考虑破解

提示:函数返回值不能是局部变量的地址。

这里有你可能用到的常量:

      char reflector[]="YRUHQSLDPXNGOKMIEBFZCWVJAT"; 
      char rotor_table[5][27] = 
      {
         "EKMFLGDQVZNTOWYHXUSPAIBRCJ",
         "AJDKSIRUXBLHWTMCQGZNPYFVOE",
         "BDFHJLCPRTXVZNYEIWGAKMUSQO",
         "ESOVPZJAYQUIRHXLNFTGKDCMWB",
         "VZBRGITYUPSDNHLXAWMJQOFECK"
      };
      char step_char[5]="RFWKA"; // Royal Flags Wave Kings Above

输入格式:

输入分为5行

第一行给出Plugboard,以空格分隔的10组, 如PO LM IU JK NH YT GB VF RE DC

第二行给出RingSetting,如TIP (T为左边齿轮内部设置,P为右边齿轮内部设置)

第三行给出需要破解的密文,如MNZUXZEZWCAYJVTODAEFBVKYXW

第四行给出已知明文中包含的单词,如CRYPTO

第五行给出最左侧的齿轮编号,如1

密文长度不超过500,单词长度不超过20

输出格式:

本题保证有且仅有唯一解

假定破解出的MessageKey=XXX, PlainText=YYYYY, RotorNum=123 (1为左边齿轮编号,5为右边齿轮编号),

则程序输出格式如下:

MessageKey=XXX
PlainText=YYYYY
RotorNum=123

输入样例:

PO LM IU JK NH YT GB VF RE DC
TIP
MNZUXZEZWCAYJVTODAEFBVKYXW
CRYPTO
1

输出样例:

MessageKey=CRY
PlainText=CRYPTOISSOINTERESTINGISNIT
RotorNum=125

参考答案:

#include<stdio.h>
#include<malloc.h>
#include<iostream>
#include<string.h>
#include<string>
using namespace std;
char reflector[] = "YRUHQSLDPXNGOKMIEBFZCWVJAT";
char rotor_table[5][27] =
{
   "EKMFLGDQVZNTOWYHXUSPAIBRCJ",
   "AJDKSIRUXBLHWTMCQGZNPYFVOE",
   "BDFHJLCPRTXVZNYEIWGAKMUSQO",
   "ESOVPZJAYQUIRHXLNFTGKDCMWB",
   "VZBRGITYUPSDNHLXAWMJQOFECK"
};
char step_char[6] = "QEVJZ"; 

struct Rotor {
	int id;
	char MK;
	char RS;
};
typedef struct Rotor* rotor;

char* crypto(rotor left, rotor right, rotor middle, char* ciphertext, char* plug);
void change(rotor left, rotor right, rotor middle);
void u_change(rotor unit);
char r_crypto(char c, rotor unit);
char rr_crypto(char c, rotor unit);

int main(void) {
	char plug[27] = "ABCDEFGHIZKLMNOPQRSTUVWXYZ";
	char relate[3];
	char RS[4];
	char MK[4];
	MK[3] = '\0';
	char ciphertext[501];
	char* plaintext;
	string PlainText;
	char word[20];
	int left, middle, right;
	int i;
	for (i = 0; i < 10; i++) {
		cin >> relate;
		plug[relate[0] - 'A'] = relate[1];
		plug[relate[1] - 'A'] = relate[0];
	}
	cin >> RS;
	cin >> ciphertext;
	cin >> word;
	cin >> left;
	rotor Left, Right, Middle;
	Left = (rotor)malloc(sizeof(struct Rotor));
	Right = (rotor)malloc(sizeof(struct Rotor));
	Middle = (rotor)malloc(sizeof(struct Rotor));
	for (middle = 1; middle <= 5; middle++) {
		if (middle == left) {
			continue;
		}
		for (right = 1; right <= 5; right++) {
			if (right == left || right == middle) {
				continue;
			}
			for (MK[0] = 'A'; MK[0] <= 'Z'; MK[0]++) {
				for (MK[1] = 'A'; MK[1] <= 'Z'; MK[1]++) {
					for (MK[2] = 'A'; MK[2] <= 'Z'; MK[2]++) {
						Left->id = left;
						Left->RS = RS[0];
						Middle->RS = RS[1];
						Right->RS = RS[2];
						Left->MK = MK[0];
						Middle->MK = MK[1];
						Right->MK = MK[2];
						Middle->id = middle;
						Right->id = right;
						plaintext = crypto(Left, Right, Middle, ciphertext, plug);
						PlainText = (string)plaintext;
						if (PlainText.find(word) != string::npos) {
							printf("MessageKey=%s\n", MK);
							printf("PlainText=%s\n", plaintext);
							printf("RotorNum=%d%d%d", left, middle, right);
							return 0;
						}
					}
				}
			}
		}
	}
	return 0;
}

char* crypto(rotor left, rotor right, rotor middle, char* ciphertext, char* plug) {
	int length, i;
	char c;
	length = strlen(ciphertext);
	char* plaintext = (char*)malloc(sizeof(char) * (length + 1));
	for (i = 0; i < length; i++) {
		change(left, right, middle);
		c = ciphertext[i];
		c = plug[c - 'A'];
		c = r_crypto(c, right);
		c = r_crypto(c, middle);
		c = r_crypto(c, left);
		c = reflector[c - 'A'];
		c = rr_crypto(c, left);
		c = rr_crypto(c, middle);
		c = rr_crypto(c, right);
		c = plug[c - 'A'];
		plaintext[i] = c;
	}
	plaintext[i] = '\0';
	return plaintext;
}

void change(rotor left, rotor right, rotor middle) {
	if (right->MK == step_char[right->id - 1] || middle->MK == step_char[middle->id - 1]) {
		if (middle->MK == step_char[middle->id - 1]) {
			u_change(left);
		}
		u_change(middle);
	}
	u_change(right);
}

void u_change(rotor unit) {
	if (unit->MK == 'Z') {
		unit->MK = 'A';
	}
	else {
		unit->MK++;
	}
}

char r_crypto(char c, rotor unit) {
	int delta = unit->MK - unit->RS;
	c = ((c - 'A') + delta + 26) % 26 + 'A';
	c = rotor_table[unit->id - 1][c - 'A'];
	c = ((c - 'A') - delta + 26) % 26 + 'A';
	return c;
}

char rr_crypto(char c, rotor unit) {
	int delta = unit->MK - unit->RS;
	c = ((c - 'A') + delta + 26) % 26 + 'A';
	for (int i = 0; i < 26; i++) {
		if (rotor_table[unit->id - 1][i] == c) {
			c = 'A' + i;
			break;
		}
	}
	c = ((c - 'A') - delta + 26) % 26 + 'A';
	return c;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
PyInstaller是一个用于将Python程序打包成可执行文件的工具,可以将Python代码和依赖的库打包为一个独立的可执行文件,方便在没有Python解释器的环境下运行程序。你可以使用以下命令来使用PyInstaller生成可执行文件:`pyinstaller -D -w xxx.py`,其中`-D`选项生成一个文件夹,里面是多文件模式,启动快,`-w`选项表示生成的可执行文件没有命令行窗口。 Enigma Virtual Box是一个免费的打包工具,可以将PyInstaller生成的多文件可执行文件打包为一个单个的可执行文件。你可以先使用PyInstaller生成多文件可执行文件,然后使用Enigma Virtual Box打包成一个可执行文件。以下是打包exe文件的步骤: 1. 使用命令`pyinstaller -D -w xxx.py`生成多文件可执行文件(xxx.py为项目主程序)。 2. 下载并安装Enigma Virtual Box。 3. 使用Enigma Virtual Box打包生成的多文件可执行文件,使其成为一个单个的可执行文件。 在打包之前,你可以先运行测试一下PyInstaller生成的exe文件是否可以正常运行。如果出现缺少dll库文件等问题,可以将缺少的文件拷贝到PyInstaller生成的目录下。当测试运行正常后,再使用Enigma Virtual Box对最终的exe文件进行打包。 关于Python镜像源的选择,你可以根据自己的需求选择合适的镜像源,如豆瓣、阿里、清华等。这些镜像源可以提供更快速的包下载速度,你可以在pip安装时指定镜像源,例如`pip install packagename -i http://pypi.douban.com/simple/`。 总结来说,PyInstaller是用于将Python程序打包成可执行文件的工具,Enigma Virtual Box是用于将PyInstaller生成的多文件可执行文件打包成一个单个可执行文件的工具。你可以先使用PyInstaller生成多文件可执行文件,然后使用Enigma Virtual Box打包成一个单个的可执行文件。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [通过pyinstaller和Enigma Virtual Box打包python程序,提升启动速度,避免了tkinter窗口使用图标等资源文件...](https://blog.csdn.net/qq_25921925/article/details/103949384)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Python开发环境(Visual Studio Code、Anaconda、PyInstaller、Enigma Virtual Box)](https://blog.csdn.net/u013420428/article/details/132376664)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值