古典密码算法(凯撒、维吉尼亚)
A. 1-1.移位密码算法
【实验目的】
1) 学习移位密码的原理
2) 学习移密码的实现
【实验原理】
- 算法原理
a) 移位密码就是对26个字母进行移位操作,可以移动任意位数,这样就实现了对明文的加密,移位操作简单易行,因此,加密解密比较简单。
b) 移位密码的基本思想:移位密码算法 c=m+k(mod 26),k可以使0<k<26的任意整数。加密算法:x=x+k(mod26),解密算法x=x-k(mod 26)。当K=3,时,为凯撒密码。
- 算法参数
移位密码算法主要有c、m、k 三个参数。c 为密文,m 是明文,k 为密钥。
- 算法流程
算法流程如下。如图所示
输入
第一行输入表明是加密还是解密,0是加密,1是解密;
第二行是加密或解密密钥,是0<k<26之间的一个整数;
第三行是明文或密文。
输出
输出是明文或密文。
输入样例1
0 6 wearesztuers 1 6 CKGXKYFZAKXY
输出样例1
CKGXKYFZAKXY wearesztuers
AC源代码
import java.util.Scanner;
/**
* @author xzx
* @date 2022/10/18
*/
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int op, key;
String text;
while (scanner.hasNext()) {
op = scanner.nextInt();
key = scanner.nextInt();
text = scanner.next();
System.out.println(CodeByKey(text, key, op == 0 ? 1 : 0));
}
}
/**
* @param text
* @param step
* @param direction 0:左移 1:右移
* @return
*/
private static String CodeByKey(String text, int step, int direction) {
StringBuilder stringBuilder = new StringBuilder();
if (direction == 0) {
step = -1 * step;
}
char startLocation = 'a';
int mod = 26;
for (int i = 0; i < text.length(); i++) {
boolean isUpper = false;
char preChar = text.charAt(i);
if (Character.isUpperCase(preChar)) {
isUpper = true;
preChar = Character.toLowerCase(preChar);
}
int preLocation = preChar - startLocation;
int offset = (preLocation + step) % mod;
if (offset < 0) {
offset += mod;
}
char cipherChar = (char) (startLocation + offset);
if (!isUpper) {
//小写转大写
cipherChar = Character.toUpperCase(cipherChar);
}
stringBuilder.append(cipherChar);
}
return stringBuilder.toString();
}
}
B. 1-2.维吉尼亚算法
【实验目的】
1) 学习维吉尼亚算法的原理
2) 学习维吉尼亚算法的实现
【实验原理】
- 算法原理
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加密。
- 算法参数
Vigenere密码算法主要有c、m、k三个个参数。c为密文,m是明文,k为密钥。
输入
第一行输入明文
第二行输入密钥
输出
第一行输出密文
第二行输出密文解密后得到的明文
输入样例1
xipuyangguang best
输出样例1
ymhnzefzhysgh xipuyangguang
AC源代码
import java.util.Scanner;
/**
* @author
* @date 2022/10/18
*/
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String plainText = scanner.nextLine();
String key = scanner.nextLine();
String cipherText = decode(plainText, key);
System.out.println(cipherText);
plainText = encode(cipherText, key);
System.out.println(plainText);
}
/**
* 加密
*
* @param plainText 明文
* @param key 密钥
* @return
*/
private static String decode(String plainText, String key) {
return CodeByKey(plainText, key, 1);
}
/**
* 解密
*
* @param cipherText 密文
* @param key 密钥
* @return
*/
private static String encode(String cipherText, String key) {
return CodeByKey(cipherText, key, 0);
}
/**
* @param text
* @param key
* @param direction 0:左移 1:右移
* @return
*/
private static String CodeByKey(String text, String key, int direction) {
StringBuilder stringBuilder = new StringBuilder();
char startLocation = 'a';
int index = 0, mod = 26;
key = key.toLowerCase();
for (int i = 0; i < text.length(); i++, index++) {
boolean isUpper = false;
char preChar = text.charAt(i);
if (Character.isUpperCase(preChar)) {
isUpper = true;
preChar = Character.toLowerCase(preChar);
}
index %= key.length();
int preLocation = preChar - startLocation;
int step = key.charAt(index) - startLocation;
if (direction == 0) {
step = -1 * step;
}
int offset = (preLocation + step) % mod;
if (offset < 0) {
offset += mod;
}
char cipherChar = (char) (startLocation + offset);
if (isUpper) {
cipherChar = Character.toUpperCase(cipherChar);
}
stringBuilder.append(cipherChar);
}
return stringBuilder.toString();
}
}