*nix 上的十六进制转换为 base64

*nix 上的十六进制转换为 base64

注意:我已将此问题标记为另一个问题的重复。但我仍保留它,因为它有示例和清晰解释的答案,因此希望它能对其他人有所帮助。

- 我需要将十六进制字符串转换为 base64,就像这样在线转换器在 *nix 中。

对于“ 5C78336D77D8DF448007D277DAD5C569”(十六进制),我知道预期输出是“ XHgzbXfY30SAB9J32tXFaQ==”(base64)。

但是当我尝试将其转换为二进制然后转换为 base64 时,我得到了这个:

[kent@server SrcFiles]$ echo "5C78336D77D8DF448007D277DAD5C569" | xxd -b
0000000: 00110101 01000011 00110111 00111000 00110011 00110011  5C7833
0000006: 00110110 01000100 00110111 00110111 01000100 00111000  6D77D8
000000c: 01000100 01000110 00110100 00110100 00111000 00110000  DF4480
0000012: 00110000 00110111 01000100 00110010 00110111 00110111  07D277
0000018: 01000100 01000001 01000100 00110101 01000011 00110101  DAD5C5
000001e: 00110110 00111001 00001010                             69.
[kent@server SrcFiles]$ echo "001101010100001100110111001110000011001100110011001101100100010000110111001101110100010000111000010001000100011000110100001101000011100000110000001100000011011101000100001100100011011100110111010001000100000101000100001101010100001100110101001101100011100100001010" | base64
MDAxMTAxMDEwMTAwMDAxMTAwMTEwMTExMDAxMTEwMDAwMDExMDAxMTAwMTEwMDExMDAxMTAxMTAw
MTAwMDEwMDAwMTEwMTExMDAxMTAxMTEwMTAwMDEwMDAwMTExMDAwMDEwMDAxMDAwMTAwMDExMDAw
MTEwMTAwMDAxMTAxMDAwMDExMTAwMDAwMTEwMDAwMDAxMTAwMDAwMDExMDExMTAxMDAwMTAwMDAx
MTAwMTAwMDExMDExMTAwMTEwMTExMDEwMDAxMDAwMTAwMDAwMTAxMDAwMTAwMDAxMTAxMDEwMTAw
MDAxMTAwMTEwMTAxMDAxMTAxMTAwMDExMTAwMTAwMDAxMDEwCg==

有人能给我指出正确的方向吗?

答案1

如果要使用xxd解码十六进制字符串,则需要使用xxd -r -p。这样,您将获得:

echo "5c78336d77d8df448007d277dad5c569" | xxd -r -p | base64
XHgzbXfY30SAB9J32tXFaQ==

-r代表反向,这样xxd将解码您的十六进制转储,也就是说-p输入是一个普通的转储(即,未修饰的十六进制字符串),没有行号等格式。

答案2

这是对原始问题评论的延续。它比我预期的要长得多;因此,将其移至答案部分。

bc是一个能够处理任意基数的数字处理器;然而,bc 命令手册

对于大于 16 的基数,bc使用多字符数字方法打印数字,其中每个较高的基数数字都打印为十进制数字。多字符数字以空格分隔。

(类似的说法出现在bc 手册页

我们所说的“base64”是对 64 个值的每个字符进行特殊分配。(见维基百科中有关 Base64 的文章

“0” 的表示形式bc为“0”;而实际的 base64 编码为“A”。

您建议的 bc 命令的输出是:

$ echo "obase=64; ibase=16; 5C78336D77D8DF448007D277DAD5C569" | bc 
 01 28 30 03 13 45 29 61 35 31 17 08 00 07 52 39 31 26 53 28 21 41

因此,如果bc输出01 28 30 03 . . .,为什么我们不能在表中查找 01、28、30 等的值(产生“B”、“c”和“e”;这与您期望的“XHg...”不同)?

首先,让我们简化这个问题。

如果我们将较短的字符串输入进去bc,比如仅输入前 2.5 个字节,输出看起来会类似:

$ echo "obase=64; ibase=16; 5C783" | bc
  01 28 30 03

但是,更短的字符串则完全不同:

$ echo "obase=64; ibase=16; 5C78" | bc
 05 49 56

这是为什么?您的原始字符串是 32 个字符(2^4*32;2^128),除以 64(2^6)需要 22 个字符(22*6=132),余数为 4。这个余数在查看输出时很重要,bc但实际上并不重要。

4 个字符的输入字符串有 2^16 个值。除以 64(2^6),它可以容纳三个 64 位字(剩余 2 位);但是,5 个字符的输入字符串有 2^20 个值,除以 2^6,需要四个字才能显示(剩余 4 位;与原始字符串中的余数相同)。

更短的输入值(5C)也具有相同的余数(2^8 / 2^6 = 2 + 4 位)

$ echo "obase=64; ibase=16; 5C" | bc
 01 28

因此,利用的这个“特征” bc,我们可以使用前两个字符来简单描述实际发生的事情。

5C二进制是01011100。在 base64 世界中,我们查看前 6 位(010111,或十进制 23),并在维基百科表中看到, 23 实际上是X。太好了!它符合您的预期!然后我们继续遍历字符串,每次 6 位。

另一方面,在 bc 中,01 28 来自哪里?回到二进制01011100。与从字符串开头开始并用“=”填充到结尾的 base64 过程相反,如果有余数(base16 字符数不是 3 的倍数),bc 会将 0 填充到输入值的开头。因此,有了前面提到的余数 4,bc 实际上将使用0000 01011100;并且在 6 位块(base64)中,最终结果为000001 011100,或 01 和 28 的十进制值。


顺便说一句,如果将输入字符串的末尾填充为 bc,使得其长度为三的倍数,则会得到与所需输出类似的结果:

$ echo "obase=64; ibase=16; 5C78336D77D8DF448007D277DAD5C5690" | bc 
 23 07 32 51 27 23 31 24 55 52 18 00 01 61 09 55 54 45 23 05 26 16

您仍然需要在表中查找 23= X、 07= H、 32=等。g

相关内容