如何使用unix命令对base64和base64URL中的数据进行编码和解码?

MAL*_*H K 8 shell base64 encoding decoding base64url

Base64编码可以通过

$ echo Some_data_to_be_converted | base64

U29tZV9kYXRhX3RvX2JlIF9jb252ZXJ0ZWQK
Run Code Online (Sandbox Code Playgroud)

Base64解码可以通过

$ echo U29tZV9kYXRhX3RvX2JlIF9jb252ZXJ0ZWQK | base64 -d

Some_data_to_be_converted
Run Code Online (Sandbox Code Playgroud)
  1. 如何实现 Base64URL 编码/解码?

  2. 将“+”替换为“-”并将“/”替换为“_”就足够了吗?

  3. 什么时候做填充“#”(添加/删除“#”要考虑)?

Tho*_*hor 22

太长了;博士

使用basenc(1)来自coreutils

$ printf "xs?>>>" | basenc --base64
eHM/Pj4+
$ printf "xs?>>>" | basenc --base64url
eHM_Pj4-
Run Code Online (Sandbox Code Playgroud)

与 一样base64(1),添加-d解码开关。

一点解释

最新版本的coreutilsincludebasenc(1)支持多种不同的编码。从其帮助屏幕:

$ printf "xs?>>>" | basenc --base64
eHM/Pj4+
$ printf "xs?>>>" | basenc --base64url
eHM_Pj4-
Run Code Online (Sandbox Code Playgroud)

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

s="xs?>>>"
Run Code Online (Sandbox Code Playgroud)

作为二进制:

$ printf "%s" "$s" | xxd -b -c1 | cut -d' ' -f2 | nl
     1  01111000
     2  01110011
     3  00111111
     4  00111110
     5  00111110
     6  00111110
Run Code Online (Sandbox Code Playgroud)

作为 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
Run Code Online (Sandbox Code Playgroud)

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


wis*_*cky 10

添加到Kaplan Ilya 的答案中,这里是一个使用标准 linux/unix 命令的命令,可以解码base64url,包括处理丢失的填充。

注意:某些版本base64可以处理缺失的填充,例如 Mac/BSD base64 -D。然而,GNUbase64 -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
# ~~~???

Run Code Online (Sandbox Code Playgroud)

解码base64url命令说明:

  • echo "$str"====添加 4 个等号
  • fold -w 4将每 4 个字符分成单独的行
  • sed '$ d'删除最后一行(无关的填充)
  • tr -d '\n'连接所有行。现在填充是正确的。
  • tr '_-' '/+'转换_/,-+.

(旁注:如果您想知道为什么不使用tr '-_' '+/',因为那将按字母数字顺序排列,那是因为这会导致invalid option因为它认为-_是一个选项。您可以这样做tr -- '-_' '+/',但交换顺序更容易。)


Kap*_*lya 7

这与@jps 的建议相同,但更短。还要记住,echo默认情况下总是在末尾添加换行符,所以当你想对它进行编码时,你必须添加-n.

echo -n "Some_data_to_be_converted" | base64 | tr '/+' '_-' | tr -d '='
Run Code Online (Sandbox Code Playgroud)

用内置的 bash 工具解码它会更复杂,因为我没有找到一种简单的方法来用“=”填充字符串,这样长度将被 4 整除。可能可以完成,awk但我没有挖掘够深。如果你有本地红宝石,它变得微不足道:

2.6.2 > require 'base64'
2.6.2 > Base64.urlsafe_encode64('test', padding: false)
 => "dGVzdA"
2.6.2 > Base64.urlsafe_decode64('dGVzdA')
 => "test"
Run Code Online (Sandbox Code Playgroud)


jps*_*jps 6

如果您已经有一个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