Enigma机密码加密解密的实现


二战时期,德军使用了一套名为Enigma的密码系统,是一种基于字符映射的密码系统。它的工作原理如下:

使用者从键盘按下一个字母后,字母会先经过三个可以转动的轮盘,称为转子,每个转子就是一个字符映射表。如:

输入

A

B

C

D

E

输出

D

E

A

B

C

一个转子的输出作为下一个转子的输入。当经过第三个转子后,输出会被送入到一个反射器。反射器和转子一样,区别在于不能转动,且映射是对称的,即如果输入c1会输出c2,那么输入c2将输出c1。经过反射器后,字母会依次反向进入三个转子,并最终显示在显示盘上。至此算完成了一个字母的加密。当加密下一个字母时,第一个转子会转动一格,转子的转动代表着映射表发生变化。如上表在转动后将变成

输入

A

B

C

D

E

输出

E

A

B

C

D

当转子转动一周再次回到初始位置时,会带动第二个转子转动一格,同理第二个转动一周后,会带动第三个转子转动。(第三个转子本题中不考虑。)

本题中的三个转子和反射器的结构如下:

转子A:QAZWSXEDCRFVTGBYHNUJMIKOLP

转子B:QWERTYUIOPASDFGHJKLZXCVBNM

转子C:QETUOADGJLZCBMWRYIPSFHKXVN

反射器:ZYXWVUTSRQPONMLKJIHGFEDCBA

使用时三个转子也可拆卸自由调节顺序,也就是说加密操作前的初始状态会有26­­*26*26*3!种。我们用6位字母来记录初始状态,并称为密钥。1-3位记录三个的转子的排列顺序(如BAC表示B转子放在最靠近键盘的位置)。4-6位记录三个转子的初始位置(如XYZ表示最靠近键盘的转子初始位置在X上)。

现在提供你一串密文和密钥,请给出它的原文。


输入

第一行输入整数n(0<n<10000),代表测试用例的数量。

接下来每个用例由两行组成,第一行由六个大定字母组成,表示密钥。第二行为待解密字符串,由大写字母组成,长度不超过10000。

输出

每一行输出解密后的明文。

样例输入

1ABCXYZ ZDBSF

样例输出

HELLO

提示

来源









这个模拟题实现方面来说不难,但是题意很难理解。。。。
想必从输入字符依次经过三个转子到反射器的地方大家都能明白,但是从反射器反向经过三个转子的地方有点难理解。

以下是样例中ABCXYZ密钥的字母对照表,方便查看
正常顺序的字母表:

1A 2B 3C 4D 5E 6F 7G 8H 9I 10J 11K 12L 13M 14N 15O 16P 17Q 18R 19S 20T 21U 22V 23W 24X 25Y 26Z 

第一个转子:

1X 2E 3D 4C 5R 6F 7V 8T 9G 10B 11Y 12H 13N 14U 15J 16M 17I 18K 19O 20L 21P 22Q 23A 24Z 25W 26S


第二个转子:

1Y 2U 3I 4O 5P 6A 7S 8D 9F 10G 11H 12J 13K 14L 15Z 16X 17C 18V 19B 20N 21M 22Q 23W 24E 25R 26T


第三个转子:

1Z 2C 3B 4M 5W 6R 7Y 8I 9P 10S 11F 12H 13K 14X 15V 16N 17Q 18E 19T 20U 21O 22A 23D 24G 25J 26L


反射器:

1Z 2Y 3X 4W 5V 6U 7T 8S 9R 10Q 11P 12O 13N 14M 15L 16K 17J 18I 19H 20G 21F 22E 23D 24C 25B 26A


那样例输入的HELLO的H为例,当H经过三个转子传入反射器的时候变为字母X,反射器传出C,此时就要倒推回去。X在反射器中是第3个字母,在正常顺序字母表中第3个字母是C,所以寻找C在第三个转子中的位置,为2。正常顺序中第2个字母为B,所以寻找第二个转子中B的位置,为19。正常顺序第19个字母是S,那么在第一个转子中寻找S,为26。那么正常顺序中第26个字母为Z,因此加密出来的字母是Z

然后就按照题目的意思来,每加密一个字母第一个转子转动一格,第一转子转动一圈带动第二转子。。。。。

以下是我的代码:
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace  std;
struct password{
    char name;
    string unit;
};
password a={'A',"QAZWSXEDCRFVTGBYHNUJMIKOLP"};
password b={'B',"QWERTYUIOPASDFGHJKLZXCVBNM"};
password c={'C',"QETUOADGJLZCBMWRYIPSFHKXVN"};
string react="ZYXWVUTSRQPONMLKJIHGFEDCBA",medi,abc="ABCDEFGHIJKLMNOPQRSTUVWXYZ";
void change_first(string &a,char t){
    int i;
    for(i=0;i<26;i++){
        if(a[i]==t){
            medi=a.substr(0,i);
            break;
        }
    }
    a=a.substr(i,26-i);
    a=a+medi;
}
void change1(int &middle,string a){
    char t=a[middle];
    int i;
    for(i=0;i<26;i++){
        if(abc[i]==t){
            middle=i;
            break;
        }
    }
}
void change2(char &re_middle,string a){
    int i;
    for(i=0;i<26;i++){
        if(a[i]==re_middle){
            break;
        }
    }
    re_middle=abc[i];
}
void add1(string &a){
    medi=a.substr(0,1);
    a=a.substr(1,25);
    a=a+medi;
}
int main(){
    int i,j,k,n;
    string t;
    scanf("%d",&n);
    while(n--){
        password sel[3];
        sel[0]=a,sel[1]=b,sel[2]=c;
        string zhuanzi[3];
        cin>>t;
        for(i=0;i<3;i++){
            for(j=0;j<3;j++){
                if(sel[j].name==t[i]){
                    zhuanzi[i]=sel[j].unit;
                    break;
                }
            }
        }
        for(i=0;i<3;i++){
            change_first(zhuanzi[i],t[3+i]);
        }
        cin>>t;
        k=0;
        while(t[k]!='\0'){
            int middle;
            for(i=0;i<26;i++){
                if(abc[i]==t[k]){
                    middle=i;
                    break;
                }
            }
            for(i=0;i<3;i++){
                change1(middle,zhuanzi[i]);
            }
            
            char re_middle=react[middle];
            for(i=2;i>=0;i--){
                change2(re_middle,zhuanzi[i]);
            }
            cout<<re_middle;
            
            k++;
            add1(zhuanzi[0]);
            if(k%26==0&&k!=0){
                add1(zhuanzi[1]);
            }
            if(k%(26*26)==0&&k!=0){
                add1(zhuanzi[2]);
            }
        }
        cout<<endl;
        
    }
    return 0;
}


  • 19
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
Enigma是一种历史悠久的密码机,用于加密和解密信息。使用Python实现Enigma加密过程需要以下步骤: 1. 定义Enigma的内部结构,包括转轮、插板、天线和反射器等组件。 2. 实现转轮的旋转功能,以保证每次加密的结果不同。 3. 实现插板功能,用于替换输入字母中的某些字母。 4. 实现天线功能,把插板替换后的字母通过转轮传递到反射器。 5. 实现反射器,用于将传入的字母反弹回转轮。 6. 最后输出加密结果。 下面是一个简单的Python代码示例: ```python # 定义转子数据 ROTOR_DATA = [ "EKMFLGDQVZNTOWYHXUSPAIBRCJ", "AJDKSIRUXBLHWTMCQGZNPYFVOE", "BDFHJLCPRTXVZNYEIWGAKMUSQO", "ESOVPZJAYQUIRHXLNFTGKDCMWB", "VZBRGITYUPSDNHLXAWMJQOFECK", ] # 定义反射器数据 REFLECTOR_DATA = "YRUHQSLDPXNGOKMIEBFZCWVJAT" # 定义Enigma类 class Enigma: def __init__(self, rotors, plugboard): self.rotors = rotors self.plugboard = plugboard def substitute(self, c, data): idx = ord(c) - ord('A') return data[idx] def encrypt(self, text): text = text.upper() # 转换为大写字母 # 插板处理 for a, b in self.plugboard.items(): text = text.replace(a, b) # 加密处理 for rotor in reversed(self.rotors): # 转轮旋转 rotor.rotate() # 进行正向变换 text = rotor.forward(text, self.substitute) # 反射器处理 text = self.substitute(text, REFLECTOR_DATA) # 加密处理 for rotor in self.rotors: # 进行反向变换 text = rotor.backward(text, self.substitute) # 插板处理 for a, b in self.plugboard.items(): text = text.replace(b, a) return text ``` 使用时,可以创建一个Enigma对象并调用encrypt方法进行加密,如下所示: ```python # 定义转轮对象 rotors = [ Rotor(ROTOR_DATA[0], 'Q'), Rotor(ROTOR_DATA[1], 'E'), Rotor(ROTOR_DATA[2], 'V'), ] # 定义插板数组 plugboard = { 'A': 'F', 'B': 'G', 'C': 'H', 'D': 'I', 'J': 'K', 'E': 'L', 'M': 'N', 'O': 'P', 'Q': 'R', 'S': 'T', 'U': 'V', 'W': 'X', 'Y': 'Z', } # 创建Enigma对象 enigma = Enigma(rotors, plugboard) # 输入要加密的内容 text = "HELLO WORLD" # 进行加密 ciphertext = enigma.encrypt(text) # 输出加密结果 print(ciphertext) ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值