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

lsmepo6l  于 2023-02-13  发布在  Shell
关注(0)|答案(4)|浏览(301)

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

$ echo Some_data_to_be_converted | base64

U29tZV9kYXRhX3RvX2JlIF9jb252ZXJ0ZWQK

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

$ echo U29tZV9kYXRhX3RvX2JlIF9jb252ZXJ0ZWQK | base64 -d

Some_data_to_be_converted

1.如何实现Base64 URL编码/解码?
1.把“+”换成“-”,把“/”换成“_”就够了吗?
1.何时填充“#"(考虑添加/删除“#”)?

kognpnkq

kognpnkq1#

时间;日期

使用coreutils中的basenc(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分别Map到/+(Wikipedia上的Base64表):

cu6pst1q

cu6pst1q2#

这和@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"
tv6aics1

tv6aics13#

除了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
# ~~~???

解码base64 url命令的说明:

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

(Side注意:如果你想知道为什么不使用tr '-_' '+/',因为它是按字母数字顺序排列的,那是因为它会产生invalid option,因为它认为-_是一个选项。你可以使用tr -- '-_' '+/',但是交换顺序会更容易。)

a5g8bdjr

a5g8bdjr4#

如果你已经有了一个base64编码的字符串,你只需要用“-”替换“+”,用“_”替换“.”,就可以得到一个base64 url编码的字符串。
echo Some_data_to_be_converted | base64 | sed 's/+/-/g; s,/,_,g'
(you可以在Execute Bash Shell Online上试用)
Base64编码将输入字节(8位)Map为6位表示。4个Base64字符可以编码4*6=24位,等于3个字节。当输入的字节数不能被3整除时,根据标准需要填充。
填充字符为=
由于=字符用于URL中的键-值对,如果您打算在URL中使用编码值,则不能直接将其用于填充。您可以省略填充,因为大多数实现仍然有效,只需忽略末尾的2或4个未使用的位。或者,如果接收方确实需要填充,必须将=替换为其URL安全表示%3d

相关问题