所以我从事密码学工作已经有一年了,尽可能多地学习我能学到的东西。我遇到的很多东西(比如 LUKS 卷的十六进制 [不是一个词,而是嘘] 编码的主密钥,或者 RSA 密钥的模数)都是用十六进制编码的。我知道十进制是十进制的一种奇特表示方式,十六进制是十六进制的一种奇特表示方式,我也知道它在数字方面的工作原理,但有些事情我无法完全理解:
- ASCII 或 UTF-8(或一般明文)如何编码基于数字系统?
- 我注意到我的企业中存在两种不同的编码方案。还有其他版本吗?为什么?
我注意到的两个(解码 LUKS 主密钥和解码 RSA 模数时)很奇怪。LUKS 主密钥,我回显密钥,将其通过管道传输到“xxd -r -p”,它会吐出实际密钥,该密钥可以放入文件中并用于解锁卷,而无需使用密钥槽。我见过的另一个版本是当我将带有附件“ibase=16;”的 RSA 模数通过管道传输到“bc”时。我使用“ibase=16;”发送到 BC 的任何其他十六进制序列都会吐出数字,没有字母。“xxd -r -p”似乎输出传统的 ASCII。
为什么BC输出数字而xxd输出ASCII文本?
我很抱歉,这是一个如此混乱的问题,但就像我之前说的,我对这个话题感到太困惑了,这不正常。
答案1
“实际密钥”是二进制字符。但是,您通常放入文件中的是十六进制表示。
由于使用了 -r 开关,xxd 输出的是 ASCII 文本,而不是十六进制表示。手册页中所说的“二进制”是指实际的字符。
ASCII 基本上只是按特定顺序排列的字符列表。首先是 NULL,然后是标头起始字符,然后是标头结束字符,等等。(参见:ASCII 图表. 代码页 437(参见:维基百科关于 CP437 的页面显示为空白、笑脸轮廓、填充笑脸等。这两个的第 65 个字符都是大写字母 A。
如果第 65 个字符是大写字母 A,这意味着我们可以根据字符在图表中的位置来跟踪它们。因此,大写字母 A 位于位置 65,即十六进制中的第 41 位(通常以 C 风格表示法表示为 0x41)。您可以在我上面提到的 ASCII 表中看到值“41”。
如何在基于数字的系统中对 ASCII 或 UTF-8(或一般明文)进行编码?
数字可以转换为其他数字,例如其他进制。例如,0x4169 相当于 0x4100 + 0x69。41 相当于大写字母 H,69 相当于小写字母 i。我不确定你为什么会怀疑数字对话是否可行。如果这仍然不清楚,请重新解释(可能通过提出另一个问题)。
I have noticed 2 different kinds of encoding schemes in my ventures. Are there more versions? Why?
当然。为什么?因为软件有多种,是由不同的人设计的。就像为什么有多种字符标准(EBCDIC、ASCII、UTF-8、Unicode)一样。其中一些是无用的(在使用 ASCII 的 8 位代码页流行之前,EBCDIC 非常流行),有些可能更容易被某些软件工具支持。现在的计算机功能足够强大,没有太多的技术限制来强制使用多种标准,但不同的程序员会做不同的事情,有时是出于不同的原因。
转换工具是存在的。标准化的缺乏是因为不需要更强/更严格/更好的标准化。如果有令人信服的好处,更多的人可能会更倾向于尝试与更大的共同趋势保持一致。
为什么BC输出数字而xxd输出ASCII文本?
bc
是一个计算器。我期望它输出数字。 xxd -r
输出 ASCII 文本,因为文档中说明了它的作用。该软件的目的是将 ASCII 文本转换为更易于输入的(十六进制)数字字符串,并将数字字符串转换为对某些软件实际上更有用的“二进制”/ASCII 字符。每个程序都在实现其自己的不同目的。
我希望这些答案能够解答您提出的问题,让事情变得更加清晰。我知道您提到了这一点,但我要指出的是,这个问题有点糟糕,因为它不是一个单一明确的问题,因此请考虑在新问题中提出后续问题。通常,最好在 Stack Exchange 上每个“问题页面”提出一个实际问题。
答案2
您的问题有部分内容不太有意义:
我使用“ibase=16;”发送到 BC 的任何其他十六进制序列都会吐出数字,没有字母。
嗯,默认的输出基数bc
是十进制:
$ echo 'ibase=16; 100' | bc
256
$ echo 'ibase=16; 1000' | bc
4096
$ echo 'ibase=16; 10000' | bc
65536
那么你期望的是什么字母呢?如果你想bc
输出十六进制数,你必须将其输出基数设置为 16。但如果输入基数和输出基数相同,则其输出将与输入相同(前导零被删除):
$ echo 'obase=16; ibase=16; 100' | bc
100
$ echo 'obase=16; ibase=16; 007F' | bc
7F
$ echo 'obase=16; ibase=16; CAFE' | bc
CAFE
$ echo 'obase=16; ibase=16; FACE' | bc
FACE
请注意,如果您想做这个毫无意义的练习,您必须说obase=16; ibase=16
或,因为之后输入的任何数字都将被解释为十六进制。如果您说,则输出基数将设置为 22(16 (十六进制) = 10 (十六进制) + 6 (十六进制) = 16+6 = 22)。ibase=16; obase=10
ibase=16
ibase=16; obase=16
“xxd -r -p”似乎输出传统的 ASCII。
要么你给出了xxd
“传统 ASCII”文本的十六进制表示,要么你对“传统 ASCII”有一个非标准的定义。TOOGAM 说,xxd -r
输出“二进制”/ASCII 字符,这是一种特殊的命名法。请注意TOOGAM 链接的“ASCII 图表”
只向上到达字符 7F,并且维基百科上的 ASCII 页面说
… ASCII 将 128 个指定字符编码为七位整数……
范围也从 00 到 7F。
xxd -r
输出八位(“二进制”)字符。这是标准 ASCII 的超集。(术语扩展 ASCII指的是八位编码,但最好放弃这个短语,因为 Unicode 已经渗透到各个领域。)由于八位(“二进制”)字符构成了标准 ASCII 的超集,
xxd -r
能输出传统 ASCII 字符;例如:
$ echo 464F4F0A | xxd -r -p
FOO
F
因为 46 是(字母表中的第 6 个字母)的 ASCII 码的十六进制表示,4F 是O
(字母表中的第 15 个字母,其中 F 是 15 的十六进制表示)的 ASCII 码的十六进制表示,0A 是换行符的 ASCII 码的十六进制表示。但是
echo 000102030405067F | xxd -r -p
将输出不可打印的 ASCII 控制字符,并且
echo 80818283A0A1A2A3 | xxd -r –p
和
echo E29885E29FB9F09F98BA0A | xxd -r –p
将输出值大于 7F 的字节。这些字符(如果有)的行为(外观)由您的终端及其设置决定。