在 2 世纪,发送机密消息的一个有效方法就是对每个字母进行位移,使得 'a' 变为 'd','b' 变为 'e',依次类推 。这样处理产生的结果看上去就像是一门外语:
L fdph, L vdz, L frqtxhuhg. —— 尤利乌斯·凯撒(Julius Caesar)
正如代码清单 9-6 所示,使用计算机以数值方式处理字符是非常容易的 。
文章插图
代码清单 9-6 处理单个字符: caesar.go
c := 'a'c=c+3fmt.Printf("%c", c)// 打印出“d”
然而,代码清单 9-6 展示的方法并不完美,因为它没有考虑该如何处理字符 'x' 、 'y' 和 'z',所以它无法对 xylophones 、 yaks 和 zebras 这样的单词实施加密 。为了解决这个问题,最初的凯撒加密法采取了回绕措施,也就是将 'x' 变为 'a' 、 'y' 变为 'b',而 'z' 则变为 'c'。对于包含 26 个字符的英文字母表,我们可以通过这段代码实现上述变换:if c > 'z' {c = c - 26}
凯撒密码的解密方法跟加密方法正好相反,程序不再是为字符加上 3 而是减去 3,并且它还需要在字符过小也就是 c < 'a' 的时候,将字符加上 26 以实施回绕 。虽然上述的加密方法和解密方法都非常直观,但由于它们都需要处理字符边界以实现回绕,因此实际的编码过程将变得相当痛苦 。回转13(rotate 13,简称ROT13)是凯撒密码在 20 世纪的一个变体,该变体跟凯撒密码的唯一区别就在于,它给字符添加的量是 13 而不是 3,并且 ROT13 的加密和解密可以通过同一个方法实现,这是非常方便的 。
现在,假设搜寻外星智能(Search for Extra-terrestrial Intelligence, SETI)的相关机构在外太空扫描外星人通信信息的时候,发现了包含以下消息的广播:
message := "uv vagreangvbany fcnpr fgngvba"
我们有预感,这条消息很可能是使用 ROT13 加密的英文文本,但是在解密这条消息之前,我们还需要知悉其包含的字符数量,这条消息包含 30 个字符,可以通过内置的 len 函数来确定:fmt.Println(len(message))// 打印出“30”
注意 Go 拥有少量无须导入语句即可使用的内置函数,len 函数即是其中之一,它可以测定各种不同类型的值的长度 。例如,在上面的代码中,len 返回的就是 string 类型的字节长度 。代码清单 9-7 展示的就是外太空消息的解密程序,你只需要在 Go Playground 运行这段代码,就会知道外星人在说什么了 。代码清单 9-7 ROT13 消息解密: rot13.go
message := "uv vagreangvbany fcnpr fgngvba"for i := 0; i < len(message); i++ {// 迭代字符串中的每一个 ASCII 字符c := message[i]if c >= 'a' && c <= 'z' {// 只解密英文字母,至于空格和标点符号则保持不变c = c + 13if c > 'z' {c = c - 26}}fmt.Printf("%c", c)}
注意,这段代码中的 ROT13 实现只能处理 ASCII 字符(字节),它无法处理用西班牙语或者俄语撰写的消息,不过接下来的一节将会给出这个问题的解决方案 。【使用 Go 语言实现凯撒加密】
推荐阅读
- 人马该怎样玩?
- 对讲机电池原理和使用注意事项
- 主流RPC框架通讯协议实现原理与源码解析
- C语言中的动态内存分配与变长数组
- C语言标准库的7类函数
- 使用cors完成跨域请求处理
- 超过35%的德国中小企业已使用人工智能技术
- 技术转载 || 使用java API进行zip递归压缩文件夹以及解压
- SpringBoot中使用dubbo实现RPC调用
- 正确的消毒柜使用方法