凯撒加密
前言
这是我的第一篇博客希望以后多多关注。
这篇文章起源于我在人工智能导论上的一次摸鱼◔ ‸◔,当时老师一节课都在脱离课本介绍,讲什么网络安全之类的问题,后面还举例子了一些加密方法巴拉巴拉,然后就开始介绍起来了凯撒加密,让大家找规律,我觉得还蛮有意思,而且比较简单,这个东西,然后在可以手动完成加密的基础上,想要体现一下俺2年算法水平,然后就尝试的实现了一下(。◕‿◕。)。
这个是当时的题目的PPT,老师让我猜一下如果密钥是DOCUMENT的话,这个密文是啥(揉眼睛 ( ‘-ωก̀ )。
第一次看这个PPT的时候,让猜凯撒加密的原理其实,一看有点难的亚子(•ิ_•ิ),但就在一瞬间突然明白辽,还是很简单的(..•˘_˘•..)。
我来介绍一下原理吧๑乛◡乛๑:
首先第一步是确定密钥的字母顺序,按照字母表来排序,所以A上面是1,然后以此类推R上面就是6了。
然后就是把原文从左往右,从上到下,在密钥下面写下去,然后就会得到这个ppt左部分这个不完整的矩阵了。再按照密钥的字母顺序从上到下来读取,就可以获得密文了,是不是很简单呀,这个手动算凯撒加密,于是我就想要使用程序做出来,由于最近再学java,于是我就要来展示一下我的java水平了。于是一个小时过后,我就写出来了我的代码(没错我写了一个小时,一部分是Java的API还不是很熟,另一个方面是,这个算法确实好几个恶心的地方QWQ)。
具体代码:
import java.util.*;
public class Main
{
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
System.out.println("请输入秘钥:");
ArrayList<Character> key_arraylist = new ArrayList<>();
String key = in.nextLine();
// <1.1>
int len_key = key.length();
// 把密钥中的字母提取出来,然后放入列表中进行排序
for (int i = 0; i < len_key; ++ i)
{
key_arraylist.add(key.charAt(i));
}
key_arraylist.sort(new Comparator<Character>(){
// 对密钥字母排序
@Override
public int compare(Character o1, Character o2){
int num = 0;
if (o1 > o2) num = 1;
else if (o1 == o2) num = 0;
else num = -1;
return num;
}
});
// 构建哈希表 根据列表中的顺序 来对每个字母构建映射
HashMap<Character, Character> map = new HashMap<>();
for (int i = 0; i < len_key; ++ i)
{
map.put(key_arraylist.get(i), (char)(i + '0'));
// System.out.println(key_arraylist.get(i) + " " + (char)(i + '0'));
}
// </1.1>
// System.out.println(key_arraylist);
System.out.println("请输入明文:");
String [] tmp_text = in.nextLine().split(" ");
String text = "";
for (int i = 0; i < tmp_text.length; ++ i)
{
text += tmp_text[i];
}
// System.out.println(text + " " + text.length());
int row = (int)Math.ceil((double)text.length() / (double)len_key);
int col = len_key;
char [][] matrix = new char [row + 100][col + 100];
int cnt = 0;
// System.out.println(row);
// <2.1>
for (int i = 1; i <= row; ++ i)
{
for (int j = 0; j < col; ++ j)
{
if (cnt >= text.length()) matrix[i][j] = '*';
else matrix[i][j] = text.charAt(cnt);
cnt ++;
}
}
// </2.1>
cnt = 0;
for(int i = 0; i < key.length(); ++ i)
{
matrix[0][cnt ++] = map.get(key.charAt(i));
}
// 测试代码
// for (int i = 0; i <= row; ++ i)
// {
// for (int j = 0; j < col; ++ j)
// {
// System.out.printf("%c", matrix[i][j]);
// }
// System.out.println();
// }
// <3.1>
// 按照第一行构架哈希表
TreeMap<Character, String> treeMap = new TreeMap<>();
for (int i = 0; i < col; ++ i)
{
String tmp = "";
for (int j = 1; j <= row; ++ j)
{
tmp += matrix[j][i];
}
// System.out.println(tmp);
treeMap.put(matrix[0][i], tmp);
}
// System.out.print(treeMap.keySet());
String res = "";
for (Character i : treeMap.keySet()){
res += treeMap.get(i);
}
System.out.println("加密结果:");
for (int i = 0; i < res.length(); ++ i){
char t = res.charAt(i);
if (t != '*') System.out.print(t);
}
// </3.1>
}
}
最后我再测试一组老师的作业,完美通过((٩(//̀Д/́/)۶))。
这个算法的几个难点分别为:٩͡[๏̯͡๏]
1.怎么确定那几个字母的顺序,并标注出来;
1.1 我采取的是哈希表解决,先对字母进行排序,然后根据排序结果,按顺序给每个字母加上一个映射,字母映射数字的形式解决,这样每个字母和自己的字母顺序就构成了一个映射。
如上面代码<1.1></1.1>
2.对于这个不完整的矩阵,怎么填充;
2.1 这里我采取的是,对于最后一行空着的部分,我使用一个非26字母的字符来填充,我用的是"*"
,这样就可以把这个矩阵填充为一个完整的矩阵了。
如上面代码<2.1></2.1>
3.最后矩阵怎么一行行的拿出来,因为不是顺序存储嘛;
3.1 我采取的方案是,在矩阵中第一行空出来,把整个矩阵都往下平移一个单位,然后把密钥各个字母对应的值,放到矩阵的第一排,然后再按照每一列的顺序,把每一列的第一个字符,当做哈希表的键,然后剩下的合并为字符串,作为哈希表的值,然后进行一波排序,最后按照哈希表,正常输出就可以了,对了记得判断一下输出的是否是"*"
如果是的话,就过滤掉。如上面代码<3.1></3.1>
第一次写博客,我在51CTO,掘金,上面都有相关的技术解答文章,名字都是一样的,希望大家可以关注下,为我指出错误,讨论学习,一起向着架构师前进吧。o(>ω<)o
如果觉得有帮助,来个一键三连吧(这个真的对我很重要o(>ω<)o)
这是我的github改算法的代码仓库,希望为开源共同成长奉献一份力量(ง •̀_•́)ง (*•̀ㅂ•́)و:https://github.com/JIKELIHUA/Chinese-Algorithm-of-University-Software-Engineering-Course.git