一、实验目的与原理
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;
}