一、实验目的与原理
1.实现古典密码学中的移位密码算法和维吉尼亚算法。
2.了解两种算法的原理,并且编写出来。
3.使用语言为C++或者Python等。
二、实验内容与记录
位移密码算法:
移位密码算法
在加密的时候需要注意大小写的转换,这个可以调用c++的<sstream>库中的函数进行解决。
1) 算法原理
a) 移位密码就是对26个字母进行移位操作,可以移动任意位数,这样就实现了对明文的加密,移位操作简单易行,因此,加密解密比较简单。
b) 移位密码的基本思想:移位密码算法 c=m+k(mod 26),k可以使0<k<26的任意整数。加密算法:x=x+k(mod26),解密算法x=x-k(mod 26)。当K=3,时,为凯撒密码。
2) 算法参数
移位密码算法主要有c、m、k 三个参数。c 为密文,m 是明文,k 为密钥。
输入
第一行输入表明是加密还是解密,0是加密,1是解密;
第二行是加密或解密密钥,是0<k<26之间的一个整数;
第三行是明文或密文。
输出
输出是明文或密文。
输入样例1
0
6
wearesztuers
1
6
CKGXKYFZAKXY
输出样例1
CKGXKYFZAKXY
wearesztuers
代码:
#include<iostream>
#include<string>
#include<cstring>
#include<cmath>
#include<sstream>
using namespace std;
string fx1(string text, int x, int y) {char cha = ' ';string truein;if (y == 0) {x = -1 * x;}char location = 'a';int length = 26;for (int i = 0; i < text.length(); i++) {//最终返回的字符串bool pan = false;char str = text[i];//判断是否大小写if (isupper(str)) {pan = true;//大写字母转换为小写str = tolower(str);}//位置改变int prelocation = str - location;//算法执行int offset = (prelocation + x) % length;if (offset < 0) {offset += length;}cha = (char)(location + offset);//小写转换大写if (!pan) {cha = toupper(cha);}truein += cha;}return truein;
}
int main()
{for(int j=0;j<2;j++) {//way是加密或者解密,key是密钥,text1是密文 int way, key, temp;string text1;cin >> way >> key;cin >> text1;int cost;if (way == 0) {cost = 1;}else {cost = 0;}string text2=fx1(text1, key, cost);cout<<text2<<endl;text2=" ";}
}
维吉尼亚算法:
维吉尼亚算法与移位算法相近,维吉尼亚算法可以想象成:应用到一个二维表格,横坐标是密钥,纵坐标是明文,两者相交的点是密文。
1) 算法原理
a) Vigenere密码是由法国密码学家Blaise de Vigenere于1858年提出的一种代换密码,它是多表代换密码的典型代表。
b) 定义:设m为某一固定的正整数,P、C和K分别为明文空间、密文空间和密钥空间,并且P=K=C=(Z26)m,对一个密钥k=(k1,k2,…,km),定义维吉尼亚密码的加解密算法如下:
Vigenere密码加密算法: ek(x1,x2,…,xm)=(x1+k1,x2+k2,…,xm+km)
Vigenere密码解密算法: dk(y1,y2,…,ym)=(y1-k1,y2-k2,…,ym-km)。
其中k=(k1,k2,…,km)是一个长为m的密钥字,密钥空间的大小为26m,所以对一个相对小的m,穷举密钥也需要很长的时间。如m=7,则密钥空间大小超过8×109,所以手工搜索非常困难。当明文的长度超过m时,可将明文串按长度m分局,然后对每一组使用密钥k加密。
2) 算法参数
Vigenere密码算法主要有c、m、k三个个参数。c为密文,m是明文,k为密钥。
输入
第一行输入明文
第二行输入密钥
输出
第一行输出密文
第二行输出密文解密后得到的明文
输入样例1
xipuyangguang
best
输出样例1
ymhnzefzhysgh
xipuyangguang
代码:
#include<iostream>
#include<string>
#include<cstring>
#include<cmath>
#include<sstream>
#include <algorithm>
using namespace std;
//加密函数
string fx1(string x, string y, int temp) {string truein;char cha = ' ';//定义起始末尾,长度等 char location = 'a';int index = 0, length = 26;transform(y.begin(), y.end(), y.begin(), ::tolower);for (int i = 0; i < x.length(); i++) {bool pan = false;char str = x[i];//判断大小写字母 if (isupper(str)) {pan = true;str = tolower(str);}//计算相对长度 index %= y.length();int nextlocation = str - location;int way = y[index] - location;if (temp == 0) {way = way * -1;}int offset = (nextlocation + way) % length;if (offset < 0) {offset += length;}cha = (char)(location + offset);if (pan) {cha = toupper(cha);}truein += cha;index++;}return truein;
}
//解密函数
string fx2(string x, string y, int temp) {string truein;char cha = ' ';//定义起始末尾,长度等 char location = 'a';int index = 0;int length = 26;//小写转换transform(y.begin(), y.end(), y.begin(), ::tolower);for (int i = 0; i < x.length(); i++) {bool pan = false;char str = x[i];//判断大小写字母 if (isupper(str)) {pan = true;str = tolower(str);}//计算相对长度 index %= y.length();int prelocation = str - location;int way = y[index] - location;if (temp == 0) {way = way * -1;}int offset = (prelocation + way) % length;if (offset < 0) {offset += length;}cha = (char)(location + offset);if (pan) {cha = toupper(cha);}truein += cha;index++;}return truein;
}
int main() {string x, y;cin >> x >> y;//加密函数 string str1 = fx1(x, y, 1);cout << str1 << endl;//解密函数 string str2 = fx2(str1, y, 0);cout << str2;
}