我正在做一个flutter项目,我尝试使用base64.decode()方法解码一些字符串时遇到了一个错误。我创建了一个简短的dart代码,它可以重现我在处理特定字符串时遇到的问题:
import 'dart:convert';
void main() {
final message = 'RU5UUkVHQUdSQVRJU1==';
print(utf8.decode(base64.decode(message)));
}
我收到以下错误消息:
Uncaught Error: FormatException: Invalid encoding before padding (at character 19)
RU5UUkVHQUdSQVRJU1==
我试过用JavaScript解码相同的字符串,它工作正常。如果有人能解释为什么我会得到这个错误,并可能告诉我一个解决方案,我会很高兴。谢谢。
3条答案
按热度按时间46qrfjad1#
Base64编码将二进制数据分解为3个完整字节的6位段,并将其表示为ASCII标准中的可打印字符。
第一步是将二进制字符串分解为6位块。Base64只使用6位(对应于2^6 = 64个字符)来确保编码数据可打印和可读。没有使用ASCII中可用的任何特殊字符。
这64个字符(因此命名为Base64)是10位数字、26个小写字符、26个大写字符以及加号(+)和正斜杠(/)。还有第65个字符称为填充符,即等号(=)。当二进制数据的最后一段不包含完整的6位时使用此字符
所以RU 5 UUKVHQUdSQVRJU 1 ==不遵循编码模式。
eqzww0vc2#
使用下划线字符“_”作为填充字符,并删除填充字节进行解码
由于某些原因,
dart:convert
的base64.decode
会阻塞用=
填充的字符串,并显示“invalid encoding before padding error”。即使使用包自己的填充方法base64.normalize
,也会发生这种情况,该方法用正确的填充字符=
填充字符串。=
确实是base64编码的正确填充字符。当输入组中可用位数少于24位时,它用于填充base64字符串。请参阅RFC 4648,第4节。然而,RFC 4648第5节是URL的base64编码方案,使用下划线字符
_
作为填充,而不是=
,以确保URL安全。使用
_
作为填充字符将使base64.decode
解码无误。为了进一步将生成的字节列表解码为Utf8,您需要删除填充字节,否则将收到“无效的UTF-8字节”错误。
请参见下面的代码。Here is the same code as a working dartpad.dev example.
kyks70gy3#
根据RFC 4648,字符串
RU5UUkVHQUdSQVRJU1==
不是兼容的base 64编码,在第3.5节“规范编码”中指出:Base 64和Base 32编码中的填充步骤如果实施不当,可能会导致编码数据发生不重要的变化。例如,如果输入仅为Base 64编码的一个八位字节,则会使用第一个符号的所有六位,但仅使用下一个符号的前两位。这些填充位必须由符合要求的编码器设置为零,这在下面关于填充的描述中进行了描述。如果不满足此属性,则基本编码数据没有规范表示,并且多个基本编码字符串可以解码为相同的二进制数据。如果满足此属性(以及本文档中讨论的其他属性),则保证使用规范编码。
在某些环境中,这种改变是关键的,因此如果填充位没有被设置为零,解码器可能会选择拒绝编码。涉及到这一点的规范可能会要求特定的行为。
(着重号后加。)
在这里,我们将手动执行Base 64解码过程。
获取编码字符串
RU5UUkVHQUdSQVRJU1==
,并从基本64字符集执行Map(如“表1:上述RFC的Base 64 Alphabet”),我们有:(使用
__
表示填充字符)。现在,将这些按8而不是6分组,我们得到
最重要的部分是在末尾,这里有一些非零位,后面跟着填充。如果前一个字符的最后四位没有解码为零,Dart实现将正确地确定所提供的填充没有意义。
因此,
RU5UUkVHQUdSQVRJU1==
的解码是不明确的。它是ENTREGAGRATIS
还是ENTREGAGRATISP
?这正是RFC声明“这些填充位必须由一致的编码器设置为零”的原因。事实上,正因为如此,我认为毫无怨言地将
RU5UUkVHQUdSQVRJU1==
解码为ENTREGAGRATIS
的实现是有问题的,因为它在默默地丢弃非零比特。ENTREGAGRATIS
的RFC兼容编码是RU5UUkVHQUdSQVRJUw==
。ENTREGAGRATISP
的RFC兼容编码是RU5UUkVHQUdSQVRJU1A=
。这进一步突出了输入
RU5UUkVHQUdSQVRJU1==
的二义性,它两个都不匹配。我建议您检查编码器,确定它为什么提供不兼容的编码,并确保您没有因此而丢失信息。