如何使用Unix命令在base64和base64URL中编码和解码数据?

19

Base64编码可以通过

$ echo Some_data_to_be_converted | base64

U29tZV9kYXRhX3RvX2JlIF9jb252ZXJ0ZWQK

Base64解码可以通过以下方式实现

$ echo U29tZV9kYXRhX3RvX2JlIF9jb252ZXJ0ZWQK | base64 -d

Some_data_to_be_converted
  1. 如何实现Base64URL编码/解码?

  2. 仅仅将"+"替换为"-","/"替换为"_"就足够了吗?

  3. 何时进行填充"#"(添加/删除"#"需要考虑)?

4个回答

20

简述

使用来自 coreutilsbasenc(1)

$ printf "xs?>>>" | basenc --base64
eHM/Pj4+
$ printf "xs?>>>" | basenc --base64url
eHM_Pj4-

base64(1) 相同,添加 -d 开关进行解码。

一点解释

coreutils 的最新版本包括 basenc(1),支持多种不同的编码。从其帮助屏幕中可以看到:

--base64          same as 'base64' program (RFC4648 section 4)
--base64url       file- and url-safe base64 (RFC4648 section 5)
--base32          same as 'base32' program (RFC4648 section 6)
--base32hex       extended hex alphabet base32 (RFC4648 section 7)
--base16          hex encoding (RFC4648 section 8)
--base2msbf       bit string with most significant bit (msb) first
--base2lsbf       bit string with least significant bit (lsb) first
--z85             ascii85-like encoding (ZeroMQ spec:32/Z85);
                  when encoding, input length must be a multiple of 4;
                  when decoding, input length must be a multiple of 5

这是一个说明差异的字符串:

s="xs?>>>"

二进制表示:

$ printf "%s" "$s" | xxd -b -c1 | cut -d' ' -f2 | nl
     1  01111000
     2  01110011
     3  00111111
     4  00111110
     5  00111110
     6  00111110

作为6位块(根据Base64读取数据):

$ printf "%s" "$s" | xxd -b -c1 | cut -d' ' -f2 | tr -d '\n' | fold -w6 | nl
     1  011110
     2  000111
     3  001100
     4  111111
     5  001111
     6  100011
     7  111000
     8  111110

请注意,块4和块8分别映射到/+维基百科上的Base64表格):


17

这与@jps的建议相同,但更简短。还要记住,默认情况下echo总是在末尾添加换行符,因此当您想要编码时,必须添加-n

echo -n "Some_data_to_be_converted" | base64 | tr '/+' '_-' | tr -d '='

使用内置的bash工具进行解码比较复杂,因为我没有找到一种简单的方法来用'='填充字符串使其长度可以被4整除。可能可以使用awk完成,但我没有深入研究。如果你有本地的ruby,这将变得微不足道:

2.6.2 > require 'base64'
2.6.2 > Base64.urlsafe_encode64('test', padding: false)
 => "dGVzdA"
2.6.2 > Base64.urlsafe_decode64('dGVzdA')
 => "test"

-n参数对于我来说是缺失的一部分。谢谢 :) - Victor Martins
我将其视为一项挑战,尝试使用Bash或标准Unix命令来填充字符串以便解码:https://dev59.com/VFMH5IYBdhLWcg3wnAWa#68921189 - wisbucky

10

在 Kaplan Ilya 的回答基础上,这里提供了一条使用标准linux/unix命令解码base64url的命令,包括处理缺失填充。

注意:某些版本的base64可以处理缺失填充,例如Mac/BSD的base64 -D。然而,GNU的base64 -d需要正确的填充。

此外,我使用的测试字符串是~~~???,而不是原问题中的Some_data_to_be_converted,以便生成+/=字符。

text='~~~???'

# encode base64
echo "$text" | base64
# fn5+Pz8/Cg==

# encode base64url
base64url=$( echo "$text" | base64 | tr '/+' '_-' | tr -d '=' )
echo "$base64url"
# fn5-Pz8_Cg

# decode base64url
echo "$base64url"==== | fold -w 4 | sed '$ d' | tr -d '\n' | tr '_-' '/+' | base64 -d
# ~~~???


解释base64url解码命令的含义:
  • echo "$str"==== 追加4个等号
  • fold -w 4 把每四个字符分开成单独的行
  • sed '$ d' 删除最后一行(多余的填充)
  • tr -d '\n' 连接所有行。现在填充正确。
  • tr '_-' '/+'_转换为/,将-转换为+

(顺便说一句:如果你想知道为什么不使用tr '-_' '+/',因为它会导致无效选项,因为它认为-_是一个选项。你可以使用tr -- '-_' '+/',但交换顺序更容易。)


8
如果您已经拥有一个base64编码的字符串,只需用"-"替换"+",用"_"替换"/"即可获得base64url编码的字符串。要实现这一点,您可以使用以下命令: echo Some_data_to_be_converted | base64 | sed 's/+/-/g; s,/,_,g' (您可以在Execute Bash Shell Online上尝试)
Base64编码将输入字节(8位)映射到6位表示法。4个base64字符可以编码4*6=24位,相当于3个字节。每当您输入的字节数不能被3整除时,必须按照标准进行填充。
填充字符是= 由于在URL中,=字符用于键值对,如果您打算在URL中使用编码值,则不能直接使用它作为填充。您可以省略填充,因为大多数实现仍将起作用并忽略2或4个未使用的位于末尾。或者,如果接收者真的需要填充,您必须将=替换为其URL安全表示形式%3d

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接