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

问题描述 投票:0回答:4

Base64编码可以通过

实现
$ echo Some_data_to_be_converted | base64

U29tZV9kYXRhX3RvX2JlIF9jb252ZXJ0ZWQK

Base64解码可以通过

实现
$ echo U29tZV9kYXRhX3RvX2JlIF9jb252ZXJ0ZWQK | base64 -d

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

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

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

shell encoding base64 decoding base64url
4个回答
25
投票

tl;博士

使用

basenc(1)
中的
coreutils

$ 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 表):


20
投票

这与 @jps 的建议相同,但更短。另请记住,默认情况下

echo
总是在末尾添加换行符,因此当您要对其进行编码时,必须添加
-n

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

使用内置 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"

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
    将每 4 个字符分成单独的行
  • sed '$ d'
    删除最后一行(无关的填充)
  • tr -d '\n'
    连接所有行。现在填充是正确的。
  • tr '_-' '/+'
    _
    转换为
    /
    ,将
    -
    转换为
    +

(旁注:如果您想知道为什么不使用

tr '-_' '+/'
,因为它会按字母数字顺序排列,那是因为这会导致
invalid option
,因为它认为
-_
是一个选项。您可以这样做
tr -- '-_' '+/'
,但交换顺序更容易。)


8
投票

如果您已经有base64编码字符串,则只需将“+”替换为“-”,将“/”替换为“_”即可获得base64url编码字符串。 要实现此目的,您可以使用以下命令:

echo Some_data_to_be_converted | base64 | sed 's/+/-/g; s,/,_,g'

(您可以尝试在线执行 Bash Shell

Base64 编码将输入字节(8 位)映射为 6 位表示形式。 4个base64字符可以编码4*6=24位,相当于3个字节。每当输入中的字节数无法被 3 整除时,就需要根据标准进行填充。

填充字符为

=

由于

=
字符用于 URL 中的键值对,因此如果您打算在 URL 中使用编码值,则不能直接使用它来填充。您可以忽略填充,因为大多数实现仍然可以工作,只是忽略末尾的 2 或 4 个未使用的位。或者,如果接收方确实需要填充,则必须将
=
替换为 URL 安全表示
%3d

© www.soinside.com 2019 - 2024. All rights reserved.