1024程序员解密游戏

    人们喜欢造节。一些人就起哄把 10 月 24 日叫做程序员节。1024 是 2 的 10 次方,是计算机存储单位的换算率,1024 字节等于 1K,1024K 等于 1M,以此类推。因此 1024 这个数字被认为与程序员相关。

    编程的本质是组合创造,是思考,优秀的程序应该正确、简单、健壮。所谓的程序员节其实毫无意义。不过在身边有两个活动,一是亲橙里旁边有一个展台派送礼品,二是下班的时候(约 18:30) Rancher 公众号推送了一个程序员解密游戏。这个游戏其实有点意思,即贴合程序员知识,又贴合大众娱乐。注意:想要自己解题的小伙伴看完图片后就此打住,不要再往下看了。

1024程序员解密游戏

    谜面主体是图片中间的一段密文,群里很快有人看出这是 摩尔斯电码(Morse code),并得到官方确认。

    摩尔斯电码(Morse code,又译为摩斯密码)是早期用于发送电报等信息的编码,与计算机使用二进制编码数据类似,摩尔斯电码使用短声嘀 di 和长声嗒 dah 两种状态编码数据。以短声嘀 di 的时间为一个时间单位 t,停顿时间也为 t,长声嗒 dah 时间为 3t 。国际摩尔斯电码给出了 26 个英文字母和 10 个阿拉伯数字的编码表,如下图所示。

1024程序员解密游戏

    摩尔斯电码并非纯二进制编码(如果使用纯二进制编码,编码间的停顿应该是无意义的)。一个字符的摩尔斯电码需要使用分隔符指明边界。摩尔斯(或者维尔?)很聪明,他想到可以使用较长时间的停顿(3t)来分隔字符,还可以使用更长时间的停顿来分割单词、句子等。停顿时间虽然有意义,但并不能引入全功能的状态位(停顿本身也是状态位的边界),因此摩尔斯电码也不是 3 进制编码,大概可以叫做 2.5 进制编码。

    书写时通常使用点(.)表示滴 di,横(-)表示嗒 dah,分割符可以使用空格或 / 等。通常空白无意义,使用 / 更容易阅读和排版。可见上述密文几乎是标准的摩尔斯电码。根据图片提示,还可以回复公众号得到可复制的文本形式密文,密文如下。

-.-/..-/..---/-/--./---/-.../--../-.-/..-/..---/.--/./-.--/
.-./-/-.-/..-/..---/--./-.-/---/-.../.--/-.-/..-/...--/-../
./--/.---/.-./-.-/..-/...--/-/--/---/-.../..-/-.-/..-/...--/
-/./-./.-../-.-./-.../../-...-/-...-/-...-/-...-/-...-/-...-

    根据编码表,就可以完成解码。为了方便人肉编码解码,还有人整理了一张字母编码表,如下图所示。

1024程序员解密游戏

    为了偷懒,直接在网上找了一个 在线翻译器 。没想到这个翻译器很粗糙,还有部分编码没翻译过来,看了下未翻译的部分是数字,敢情这个翻译器只认识英文字母。

1024程序员解密游戏

    还好数字部分不多,而且数字编码规则很简单(共 5 位,点在前每点加一,横在前大于 5,每横加一),可以人肉翻译补齐,如 ..---2 。这时有人在群里贴出了解码后的结果,这样是不对的,透露答案。于是我直接将其复制出来,如下,简单核对了一下,应该没问题。

KU2TGOBZKU2WEYRTKU2GKOBWKU3DEMJRKU3TMOBUKU3TENLCBI

    稍后,官方宣布截止到 19:40 已有超过 34 人解密成功,但决定再追加 34 个名额。

    显然,解码后的这段文本仍然是一段编码。官方透露第二层加密的线索也在图片中,还确认 2 的 5 次方里有秘密,这样是不对的,透露答案。2 的 5 次方是 32,于是我打开 python3 尝试直接用 base32 解码试试。

$ python3
Python 3.6.8 (default, Oct  7 2019, 12:59:55) 
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import base64
>>> base64.b32decode('KU2TGOBZKU2WEYRTKU2GKOBWKU3DEMJRKU3TMOBUKU3TENLCBI')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.6/base64.py", line 205, in b32decode
    raise binascii.Error('Incorrect padding')
binascii.Error: Incorrect padding

    提示编码没有填充对齐,难道是前面摩尔斯电码没有解码完吗?回头看,果然在编码结尾 CBI 后,还有 -...- 这样的编码,上述国际摩尔斯电码表里查不出这个编码,可能是某种扩展编码,也可能根本就毫无意义。再看了下,发现原密文结尾连续出现 6 次出现此编码,或许就只是用来填充对齐 base32 编码。不管了,先尝试补 6 个 = 上去做填充对齐,再次尝试 base32 解码,竟解码成功。

>>> base64.b32decode('KU2TGOBZKU2WEYRTKU2GKOBWKU3DEMJRKU3TMOBUKU3TENLCBI======')
b'U5389U5bb3U4e86U6211U7684U725b\n'

    解码结果出来一些数字。本来准备好解密的某一步要用上 1024 这个数字(活动源头 + 图片中有隐约出现),但同时注意到每隔 4 个字符规律的出现一个大写的 U,结尾还有一个换行符 \n,熟悉 Java 或者 JSON 字符串转义的同学应该能猜到,这难道是变体的 Unicode 编码?注意:在 JSON 或 python3 里,2 字节范围的 Unicode 字符应该使用小写的 \u 转义,即 \uXXXX 的形式。手动解码一下试试,果然得到有意义的文字字符,总共没几个字符,全部手动解码即可。在英文编码间兜兜转转,最终通过 Unicode 回归伟大的中文。

>>> chr(0x5389)
'厉'
>>> chr(0x5bb3)
'害'

解码结果为 厉害了我的牛,这应该就是最终解密结果了,公众号回复验证成功,不过赶不上前 n 名了。

最后,收获是学习了摩尔斯电码(然而并没有什么用?),缺憾是准备好的 1024 这个数字竟然没用上。

上一篇:JMeter 压测 MQTT 消息


下一篇:Eclipse教程1 - 3分钟理清Maven依赖