注意:我已将此问题标记为另一个问题的重复。但我仍保留它,因为它有示例和清晰解释的答案,因此希望它能对其他人有所帮助。
- 我需要将十六进制字符串转换为 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