标准电码,但使用UTF8作为回退编码。
标准电码原本是用于在电报中传送中文信息的一种编码。它将常用字列表并指派唯一的四字编码。
例如汉字,它的编码是3352。它提供了一种更紧凑的编码中文的方式:
标准电码只需要2字节(实际取值为0000到9999),而UTF-8则平均使用3字节。
一般来说,UTF-8 是处理所有类型字符的最佳选择,但在讨论长度受限的编码时,标准电码就变得非常有用。
这个程序是为明信片上的文本编码而编写的。而我们并不想使用base58来表示加密数据,但又希望获得一定程度的隐私。 因此,该程序将中文编码为标准电码,如果有字符缺失,则使用原始UTF-8编码或压缩UTF-8编码。
手写和输入数字要比base64或base58字符串简单得多。
程序是这样设计的:当书写明信片时,我通过命令行选项、文件或标准输入流将文字编码,这个程序将输出对应的 电码数字,我只需要将这些数字抄写到明信片上。
当其他人收到明信片后,他可以将这些数字原封不动的敲入程序,然后程序就会显示出解码的文字。
这个程序使用jlink构建,搭配zulu 21 jdk,所以从技术上来说,你不需要在电脑上额外安装Java运行环境
就可以使用本程序。
前往发布页面,下载对应的构建版本,然后调用./ctc应该就万事大吉了。
目前还没有可用于作为依赖的发布。这个程序不是作为依赖编写的,我也没有将其作为依赖测试,因此 我不想让别人无意间将其作为依赖使用并造成灾难。你可以尝试使用jitpack,但我无法向你保证结果。
如果呼声很高的话,请创建一个Issue,我会将其作为一个依赖发布的。
你可以使用命令行选项、文件和标准输入流进行编码:
./ctc encode -t "天匠染青红,花腰呈袅娜。"
./ctc encode -f message.txt
echo "天匠染青红,花腰呈袅娜。" | ./ctc encode -c UTF-8当-t和-f选项同时出现时,-t <text>会覆盖-f <file>。
当你使用标准输入流时,除非关闭输入流,否则你需要手动告诉程序你写完了。在新的一行中输入EOF然后回车即可。
你也可以使用--eof=EOT选项来修改这个标志。这样你就可以使用EOT来代替EOF了。
你还可以修改每行打印多少个电码。但请务必知悉,这最终会受限于你终端的宽度,如果你设定的值太宽,则终端会断行。
默认情况下将适应你的终端,你可以通过-w 6来设置为每行6个。
当使用标准输入流时,在Windows系统上会有字符集的问题。
默认情况下程序使用UTF-8字符集进行输入输出。
但在Windows上,程序将在默认地区设置为zh-CN时使用GBK字符集;
或者在默认地区设置为zh-TW时使用BIG5字符集。
如果你不想要这个功能,你可以使用-c UTF-8来强制程序使用UTF-8字符集。
虽然程序支持台湾的BIG5字符集,但标准电码使用的是大陆的版本,因此所有字符将会被当成UTF-8编码。
请务必先验证程序的输出,再将数字抄写到明信片上。 有时如果你不仔细检查的话,字符集的问题会无意中打你个措手不及。
解码和编码差不多,但是更简单。 解码时程序只用UTF-8,这在包括Windows在内的系统上的大多数终端都可以正常工作。
解码时有三个命令行选项:-t、-f和--eof。
你可以输入任何字符,程序将会忽略他们并且只留下0到9的数字。所以如果你不小心输入了字母或其他东西, 不用担心,继续敲就好了。
./ctc decode -t "1131 0561 2676 7230 4767 9976 5363 5212 0701 5934 1226 9975 84"从v1.0.0版本开始,我移除了旧的置换加密,因为它不安全。 作为替代,我加入了使用ChaCha20流密码的加密。
ChaCha20流密码首先生成一系列伪编码,范围在0000到9999之间,记作key。 对于每个CTC编码结果,使用如下公式计算密文:
enc = (code + key) % 10000
解密时,使用同样的密钥和nonce将生成同样的伪编码系列:
code = (enc - key + 10000) % 10000
Nonce将在加密时生成,并必须在解密时通过命令行选项--nonce或-n传入。
密钥(-k或--key)会根据不同加密模式有不同的解读。
如果使用对称加密,则密钥将被按照utf8编码,并进行SHA3-256运算。 结果将作为ChaCha20流的密钥。
如果使用非对称加密,则密钥将被作为hex字符串解码,并且当作私钥。
公钥则同样按照hex字符串解码,从 --dh hex选项中取得。
然后使用X25519 ECDH算法计算共享密钥,最后应用SHA3-256运算。
结果将作为ChaCha20流的密钥。
对于非对称加密,要生成私钥,请用openssl rand -hex 32。
要查看对应的公钥,请用./ctc pubkey <your private key in hex>。
启用加密时,程序会自动生成一个MAC摘要用以确保信息的完整性。
该摘要会在加密时自动生成,并必须在解密时通过命令行选项--mac或-m传入。
本程序在简单的查表和替换之上还有更复杂的预处理。 标准电码取自:https://en.wiktionary.org/wiki/Appendix:Chinese_telegraph_code/Mainland_1983
在开始编码之前,我们需要进行如下替换来获得更简短的编码:
- 换行(
\n)将被替换为〷(电码9999) - 类似
10日的词将被替换为㏩(电码9910)
这些操作将会减少一些电码,并且这种变换对用户是透明的。 在解码时将会应用它的逆变换来确保解码出来的问题是正确的。
当遇到标准电码中没有的字符时,程序将其存储在一个缓冲区中,并按批处理。
例如编码大家好,my name is XXX。时,未知缓冲区将是my name is XXX。
随后缓冲区内的数据将会按照UTF-8编码。编码后将会被LZMA2以最大等级压缩(字典大小256KB),
如果压缩后的长度小于原始长度,则使用压缩后的编码。
对于原始UTF-8编码,它将被包括在电码9992和9993之间。内容则是以0000到9991来表示。
表示的方法类似base9992但以纯数字形式表现。
对于压缩的UTF-8编码,它将被包括在电码9994和9995之间。内容的表示方法相同。
为了确保编码后的数据完整性,以及确保打字的时候没有出现错误, 我在编码后的每行输出后面追加了校验和。
比如,输入天匠染青红,花腰呈袅娜。所对应的编码是:
1131 0561 2676 7230
4767 9976 5363 5212
0701 5934 1226 9975
当打印每一行的输出时,程序将会在每行结尾追加ISO 7064 mod 97–10校验和。
因此实际输出是这样的(使用-w 4来指定每行打印4个电码):
1131 0561 2676 7230 17
4767 9976 5363 5212 92
0701 5934 1226 9975 62
***解码时,校验和是必须的。***如果你不知道校验和,或者校验和污损无法分辨,使用00代替(必须是两位)。
同时,换行也是必须的,因为解码时程序独立地校验每行数据,所以你不能将两行数据合并为一行。
你必须照原样输入(空白字符是允许的,他们会被自动忽略)。
欢迎任何贡献,但我无法保证你的PR会被接受。 如果有任何问题,可以创建一个Issue,但我无法保证一定会解答你的问题。
太长不看:我对于这个程序不给出任何保证,除非你付给我钱。