凯撒密码(一)

  “恺撒密码”据传是古罗马恺撒大帝用来保护重要军情的加密系统。(即今天我们所说的:替代密码)

  它是一种代换密码,通过将字母按顺序推后起3位起到加密作用,如将字母A换作字母D,将字母B换作字母E。据说恺撒是率先使用加密函的古代将领之一,因此这种加密方法被称为恺撒密码。

  假如有这样一条指令:

  明文(小写):ji xiao jing

  用恺撒密码加密后就成为:

  密文(大写):ML ALDR MLQJ

  如果这份指令被敌方截获,也将不会泄密,因为字面上看不出任何意义。

  这种加密方法还可以依据移位的不同产生新的变化,如将每个字母左19位,就产生这样一个明密对照表:

  明文:a b c d e f g h i j k l m n o pq r s t u v w x y z

  密文:T U V W X Y Z A B C D E F G H I J K L M N O P Q R S

  在这个加密表下,明文与密文的对照关系就变成:

  明文:b a i d u

  密文:UTB WN

先做一个如下的界面:

相关的一些控件名:

输入区文本框txtInput

输出区文本框txtOutput

密钥区文本框txtKey

因为加密和解密互为逆过程,所以我们把加密和解密做成一个同函数,如果加密的key是3,解密时就转换为-3,这样能节省一些代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
private void Caesar(int choose)
{
bool flag;
int key;
int len;
int i;
int member;
string info = info = txtInput.Text;
flag = int.TryParse(txtKey.Text, out key);

if (flag == true && info.Length > 0)
{
if (choose != 1)
key = -key;

txtOutput.Clear();
len = info.Length;
for (i = 0; i < len; i++)
{
member = info[i];
if (member >= 'a' && member <= 'z')
{
member = (member + key % 26);
if (member < 'a') member = (member + 26);
if (member > 'z') member = (member - 26);
txtOutput.Text += (char)member;
}
else if (member >= 'A' && member <= 'Z')
{
member = (member + key % 26);
if (member < 'A') member = (member + 26);
if (member > 'Z') member = (member - 26);
txtOutput.Text += (char)member;
}
else if (member >= '0' && member <= '9')
{
member = (member + key % 10);
if (member < '0') member = (member + 10);
if (member > '9') member = (member - 10);
txtOutput.Text += (char)member;
}
else if (member >= 0 && member <= 47)
{
member = (member + key % 48);
if (member < 0) member = (member + 48);
if (member > 47) member = (member - 48);
txtOutput.Text += (char)member;
}
else if (member >= 58 && member <= 64)
{
member = (member + key % 7);
if (member < 58) member = (member + 7);
if (member > 64) member = (member - 7);
txtOutput.Text += (char)member;
}
else if (member >= 91 && member <= 96)
{
member = (member + key % 6);
if (member < 91) member = (member + 6);
if (member > 96) member = (member - 6);
txtOutput.Text += (char)member;
}
else
{
txtOutput.Text += (char)(member + key);
}
}
}
else
{
MessageBox.Show("密钥输入有误!/文本出现错误!");
txtKey.Clear();
txtKey.Focus();
}
}

上面代码可以看到通过接受choose 的参数来确定是加密还是解密,从而选择是key还是-key。 这段代码对字母和数字进行了可循环加密,对于其他符号直接输出。

对于加密方法的解释:

1
2
3
4
5
6
7
if (member >= 'A' && member <= 'Z')
{
member = (member + key % 26);
if (member < 'A') member = (member + 26);
if (member > 'Z') member = (member - 26);
txtOutput.Text += (char)member;
}

先用key对26取模,因为超过26相当于一个循环。比如C用28加密,字母总共26个,如果是26,则又回到了C本省,现在是28,所以C回到本身后又前进2个变成了E。对这种情况先取模,防止多余的运算。

网上还有一种算法

1
member = (member - 'A' + key) % 26 + 'A';

这种方法加密没有任何问题,但是用同一个函数进行解密过程就出现问题了。

看一下他的思路,先对字母本省减’A’,得到了相对A的偏移量,然后和key运算得到加密后的相对偏移量,最后再加’A’,得到结果,这个算法很好的解决了”后溢”问题,什么是”后溢”问题呢? 比如X用3加密。X先减’A’,得到偏移量23,然后23 + 3得到26, 26对26取模得0,所以最后偏移量是0,’A’ + 0 还是’A’。所以X用3加密就是A。(….’X’,’Y’,’Z’,’A’…..)这样加密没有让X+3变成字母以外的编码值。但是这个算法没法解决”前溢”。例如A对3解密,是上述过程的逆,结果应该是X。因为是解密,key就变成了-3。先是计算偏移量’A’-‘A’ = 0,计算最终偏移量0 - 3 = -3。 对26取模,得-3,再加’A’得到的结果是member = ‘A’ - 3; 这就出现一个问题,A的ASCII码前面是什么?肯定不是A~Z之间的字母了。是其他符号。(’[ ‘, ‘]’ , ‘/‘ , ‘A’ , ‘B’ , ‘C’…….)所以我淘汰了这种算法。

加密:

解密:(错误的key)

作者

Wu Rang

发布于

2010-10-24

更新于

2021-12-06

许可协议

评论