为什么Base64.decode对于不同的字符串产生相同的字节数组?

7

我正在使用URL安全的Base64编码来编码我的随机生成的字节数组。但是我在解码时遇到了问题。当我解码两个不同的字符串(除最后一个字符外都相同)时,它会产生相同的字节数组。例如,对于"dGVzdCBzdHJpbmr""dGVzdCBzdHJpbmq"这两个字符串,结果是相同的:

Array(116, 101, 115, 116, 32, 115, 116, 114, 105, 110, 106)

在编码/解码方面,我使用java.util.Base64库:

// encoding...
Base64.getUrlEncoder().withoutPadding().encodeToString(myString.getBytes())
// decoding...
Base64.getUrlDecoder().decode(base64String)

这个碰撞的原因是什么?它会在除了最后一个字符之外的其他字符上发生吗?我应该如何解决这个问题,并确保对每个不同的字符串解码返回不同的字节数组?

1
你确定 withoutPadding() 选项是个好主意吗? - Harald K
1
从根本上说,同一个数组可以用两种不同的方式进行编码,这并不重要。重要的是,如果你拿到一个数组,对其进行编码,然后再解码,你能够得到相同的数组。 - T.J. Crowder
1
这并不意味着有两个字符串输出相同就不是非常有趣了。:-) 我很确定这只是因为末尾存在未使用的位(因为Base64在字节边界上编码八位组),但我必须计算出这些位才能确定。 - T.J. Crowder
@haraldK 我用它来删除末尾的“=”字符。实际上,我尝试了填充,结果是一样的。 - ovunccetin
3个回答

10
你看到的问题是由于“result”中的字节数(11个字节)无法完全“填充”Base64编码字符串的最后一个字符造成的。
请记住,Base64将每个8位实体编码为6位字符。结果字符串需要正好11 * 8/6个字节或14 2/3个字符,但不能写入部分字符。仅第一个4位(或最后一个字符的2/3)是有效的。最后两位未解码。因此,以下所有内容都是如此:
dGVzdCBzdHJpbmo
dGVzdCBzdHJpbmp
dGVzdCBzdHJpbmq
dGVzdCBzdHJpbmr

所有解码结果都会变成相同的11个字节(116, 101, 115, 116, 32, 115, 116, 114, 105, 110, 106)。

顺便提一下,如果不进行填充,某些解码器将尝试对“最后”一个字节进行解码,这样你就会得到一个12个字节的结果(最后一个字节不同)。这就是我发表评论的原因(询问是否使用withoutPadding()选项是一个好主意)。但你的解码器似乎处理得很好。


0
也许这就是 Base64 的编码和解码方式......看看这个this是否有帮助。 阅读下面的描述以了解 Base 64 的实际工作原理。如果数组字符串在末尾存在差异,则编码后的值将可能反映在相同的位置上。

0

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