【问题标题】:fail to correctly encode and decode using java.util.Base64无法使用 java.util.Base64 正确编码和解码
【发布时间】:2016-07-18 12:56:46
【问题描述】:

让“awids”为 12 个字符长度的 id,以 64 为基数 (A-Z a-z 0-9 "-" "@")。这是输入。

我的最终目标是在这些 awid 和 UUIDs 之间创建一个双射映射,使用一些填充,将 awid 作为初始输入。

尝试使用java.util.Base64 在解码和编码后我没有得到初始值。我犯了什么愚蠢的错误? :)

对于我在下面展示的可重现示例,输出是错误的,因为在decode()-encode() 之后没有返回输入字符串并且没有保留双射(Q39s/LQ39s/A 都映射到同一个值)。

------------------------------------------> Q39s/L(6 [51 33 39 73 2f 4c]) 4 [43 7f 6c fc] -> 6 [51 33 39 73 2f 41] -> Q39s/A (6 [51 33 39 73 2f 41]) 4 [43 7f 6c fc] -> 6 [51 33 39 73 2f 41] -> Q39s/A (6 [51 33 39 73 2f 41])

这是一个可重现的例子:

import java.nio.charset.StandardCharsets; import java.util.Base64; import java.util.StringJoiner; public class StackOverflowQuestion { public static void main(String[] args) { String halfAwid = "Q39s/L"; byte[] sigBits = Base64.getDecoder().decode(halfAwid.getBytes(StandardCharsets.UTF_8)); byte[] actualSigBits = Base64.getEncoder().withoutPadding().encode(sigBits); String actualHalfAwid = new String(actualSigBits, StandardCharsets.UTF_8); byte[] sigBits2 = Base64.getDecoder().decode(halfAwid.getBytes(StandardCharsets.UTF_8)); byte[] actualSigBits2 = Base64.getEncoder().withoutPadding().encode(sigBits2); String actualHalfAwid2 = new String(actualSigBits2, StandardCharsets.UTF_8); System.out.println("----------------------------------------------> " + halfAwid + " (" + toHexString(halfAwid) + ") " + "\n" + " " + toHexString(sigBits) + " -> " + toHexString(actualSigBits) + " -> " + actualHalfAwid + " (" + toHexString(actualHalfAwid) + ") " + "\n" + " " + toHexString(sigBits2) + " -> " + toHexString(actualSigBits2) + " -> " + actualHalfAwid2 + " (" + toHexString(actualHalfAwid2) + ")" + ""); } private static String toHexString(byte[] bytes) { StringJoiner joiner = new StringJoiner(" ", "" + bytes.length + " [", "]"); for (byte b : bytes) { joiner.add(String.format("%02x", b)); } return joiner.toString(); } private static String toHexString(String text) { return toHexString(text.getBytes()); } }

不要犹豫,指出我在代码中出现的任何其他错误,即使它们与问题没有直接关系。谢谢。

【问题讨论】:

    标签: java-8 base64 decode encode


    【解决方案1】:

    如果您将编码数据视为整个字节(或 ASCII 字符)的序列,Base64 编码并不是所有输入大小的双射映射。 Base64 将 8 位单元编码为 6 位单元(每个单元产生 64 种可能的组合),因此当您编码 4 个字节,即4×8=32 位时,您将得到32/6=5⅓ 单元输出,这意味着输出的第六个单元不会使用所有位。

    换句话说,当您将由 64 个已定义字符中的 6 个组成的任意字符串视为经过 Base64 编码时,您会将 64⁶ 组合的字符串投影到具有 256⁴ 组合的六个字节的“源”序列,​​这意味着数据丢失。

    如果您选择可以投影到整数单位的输入大小,例如,您可以使用 Base64 编码作为双射映射。显然,六个源字节可以编码为八个 Base64 编码字节。但它不适用于六个编码字节。有趣的是,它将适用于您实际所需的大小,因为 9 个源字节将被编码为正好 12 个编码字节:9×8=7272/6=12

    【讨论】:

    • 你是对的。谢谢你。我将 12 个编码字符拆分为 8 + 4 个字符,这将导致我得到 6 个字节 (msb) + 3 个字节 (lsb)。
    • 发布问题后我发现的清除资源(是的,我知道我应该从它开始)en.wikipedia.org/wiki/Base64
    猜你喜欢
    • 1970-01-01
    • 2020-11-26
    • 1970-01-01
    • 2017-03-31
    • 2015-08-21
    • 1970-01-01
    • 2022-10-20
    • 2015-04-17
    • 1970-01-01
    相关资源
    最近更新 更多