2021.3.13
虽然解密还是有问题并且我改不出来
感动中国我做到了我做到了
不要管排版了我超超超开心quqqqqq
是密码学的作业,被好多小坑绊到灰头土脸抱膝对墙哭,但我还是写出来了!!!
才看到去年差不多也是三月的时候我居然发过东西哈哈哈哈哈哈
好可爱啊那时候
当时还在经管→五月份动了转专业的念头→战战兢兢递交申请→成功进了信院
(虽然因为绩点计算方式在补完大一的课之前拿不了学习奖学金有些委屈quq)
(并且意识到在洛谷学了一个假期的题解好多是初中的孩子们写的而信心崩塌)
我是个说到做到的小朋友嗷
真的有进步!! 就好开❤
我要把它放在这里,看看再一年后回来的我会是什么样子
也许一年后的我可以唰唰把它改好
我在等你嗷 未来的我自己
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<string>
#define MXKEY 50
using namespace std;
char orinkey[MXKEY], key[26], PwTable[5][5];
void CreateKey(char ok[], char key[])
{
int i, pos=0;
int shown[26] = { 0 }; //0未出现过
for (i=0; ok[i] != '\0'; i++)
{
if (ok[i]<'a'||ok[i]>'z')
continue;
if (shown[ok[i]-'a'] == 0)
{
key[pos++] = ok[i];
shown[ok[i]-'a'] = 1;
}
}
cout<<"\n生成的密钥为:";
for (i=0; i<pos; i++)
cout<<key[i];
}
void CreatePwTable(char key[], int klen)
{
int i, j, x=0, y=0, cnt=0;
int shown[26] = { 0 };
for (i=0; i<klen; i++)
{
if(key[i] == 'j') key[i]='i';
PwTable[x][y++] = key[i];
cnt++;
shown[key[i]-'a'] = 1;
if (cnt%5 == 0)
{
x++; y=0;
}
}
for (i=0; i<26; i++)
{
if (shown[i] == 0)
{
if(i == 9) //j→i
PwTable[x][y++] = 'i';
else
{
PwTable[x][y++] = i+'a';
cnt++;
if (cnt%5 == 0)
{
x++; y=0;
}
}
}
}
cout<<"\n\n生成的密码表为:\n";
for (i=0; i<5; i++)
{
for (j=0; j<5; j++)
cout<<PwTable[i][j]<<' ';
cout<<endl;
}
}
void GetLoc(char c, int& x, int& y)
{
int i, j;
for (i=0; i<5; i++)
for (j=0; j<5; j++)
if(PwTable[i][j] == c)
{
x = i; y = j;
return;
}
}
void Encryption(string& pt, string& ct)
{
int plen=pt.length();
int i, x1, x2, y1, y2;
char a, b;
for(i=0; i<plen; i+=2)
{
a = pt[i];
b = pt[i+1];
GetLoc(a, x1, y1);
GetLoc(b, x2 ,y2);
if(x1 == x2)
{
ct.push_back(PwTable[x1][(y1+1)%5]);
ct.push_back(PwTable[x1][(y2+1)%5]);
}
else if(y1 ==y2)
{
ct.push_back(PwTable[(x1+1)%5][y1]);
ct.push_back(PwTable[(x2+1)%5][y1]);
}
else
{
ct.push_back(PwTable[x1][y2]);
ct.push_back(PwTable[x2][y1]);
}
}
cout<<"\n生成的密文为:"<<ct<<endl<<endl;
}
void PretreatPT(string &pt)
{
int i, j;
for(i=0; i<pt.length(); i+=2)
{
j = i+1;
if(pt[i] == pt[j])
{
if(pt[i] == 'x') pt.insert(j, "q");
else pt.insert(j, "x");
}
if(pt[j] == '\0')
{
if(pt[i] == 'x') pt.insert(j, "q");
else pt.insert(j, "x");
}
}
cout<<"\n明文预处理后为:"<<pt<<endl;
}
void PretreatCT(string &pt)
{
int i, j, len = pt.length();
if(len%2==0)
{
if(pt[len-1]=='x' || pt[len-1]=='q')
pt.erase(len-1, 1);
}
for(i=0; i<len-1; i++)
{
j = i+1;
if(pt[i]==pt[j+1] && pt[j]=='x') pt.erase(j, 1);
if(pt[i]=='x'&&pt[j+1]=='x'&&pt[j]=='q') pt.erase(j, 1);
}
cout<<"\n还原出的明文为:"<<pt<<"(i可能为j,或者明文含有如exe的特殊格式(两个相同字母之间隔着x)会出错)"<<endl;
}
void Decryption(string& pt, string& ct)
{
int plen=pt.length();
int i, x1, x2, y1, y2;
char a, b;
for(i=0; i<plen; i+=2)
{
a = pt[i];
b = pt[i+1];
GetLoc(a, x1, y1);
GetLoc(b, x2 ,y2);
if(x1 == x2)
{
if(y1-1==-1)
ct.push_back(PwTable[x1][4]);
else
ct.push_back(PwTable[x1][(y1-1)%5]);
if(y2-1==-1)
ct.push_back(PwTable[x1][4]);
else
ct.push_back(PwTable[x1][(y2-1)%5]);
}
else if(y1 ==y2)
{
if(x1-1==-1)
ct.push_back(PwTable[4][y1]);
else
ct.push_back(PwTable[(x1-1)%5][y1]);
if(x2-1==-1)
ct.push_back(PwTable[4][y1]);
else
ct.push_back(PwTable[(x2-1)%5][y1]);
}
else
{
ct.push_back(PwTable[x1][y2]);
ct.push_back(PwTable[x2][y1]);
}
}
cout<<"\n未彻底复原的明文为:"<<ct<<endl;
}
int main()
{
int i, len, choice;
string plaintxt, ciphertxt, ct2, pt2;
cout<<"约定密钥按行排列、j替换为i处理、交叉情况下横向替换、插入字母为x(xx则插入q)\n";
while(1)
{
cout<<"\n选择操作:1--加密, 2--解密, 3--退出\n";
cin>>choice;
if(choice==1)
{
cout<<"输入密钥,要求为完整小写单词:";
cin>>orinkey;
CreateKey(orinkey, key); //根据输入生成密钥
CreatePwTable(key, strlen(key)); //密钥编制出密码表
cout<<"\n输入需要加密的明文:";
cin>>plaintxt;
len = plaintxt.length();
for(i=0; i<len; i++)
{ //j→i
if(plaintxt[i]=='j') plaintxt[i]='i';
}
PretreatPT(plaintxt); //明文预处理
Encryption(plaintxt, ciphertxt); //生成密文
}
if(choice==2)
{
cout<<"输入密钥,要求为完整小写单词:";
cin>>orinkey;
CreateKey(orinkey, key); //根据输入生成密钥
CreatePwTable(key, strlen(key)); //密钥编制出密码表
cout<<"\n输入密文进行解密:";
cin>>ct2;
Decryption(ct2, pt2);
PretreatCT(pt2);
}
if(choice==3)
break;
}
return 0;
}