将包含“-”和“_”等字符的字节数组解码为base64时出错。

3

我正在尝试对一个字节数组进行Base64解码,只要字节数组中不包含“-”或“_”等特殊字符,一切都可以正常运行。但是当字节数组包含“-”时,就会抛出异常:

java.lang.IllegalArgumentException: Illegal base64 character 2d
    at java.util.Base64$Decoder.decode0(Base64.java:714)
    at java.util.Base64$Decoder.decode(Base64.java:526)

当字节数组包含'_'时,就会抛出异常。

java.lang.IllegalArgumentException: Illegal base64 character 5f
    at java.util.Base64$Decoder.decode0(Base64.java:714)
    at java.util.Base64$Decoder.decode(Base64.java:526)

即代码在字符2d到5f之后的差异。

这些代码是什么?我如何解码任何值,而不管代码中是否有这些字符?

以下是我的代码片段:

import java.util.Properties;
import java.util.Base64;
import java.io.*;
...

public class BasicSample {

    public static void main(String[] args) {
      byte[] encoded = res.getBytes("s_id");
      System.out.printf("\nInside Byte %s\n",new String(encoded) );
      try {
        byte[] decoded = Base64.getDecoder().decode(encoded);

        System.out.printf("\nDecoded Byte %s\n",new String(decoded, "UTF-8") );
      } catch(Exception e) {
        e.printStackTrace();
      }
   }

}
2个回答

4

解决方案

将下面的行中的'-'替换为'+',将'_'替换为'/'

byte[] decoded = Base64.getDecoder().decode(encoded.replace('-', '+').replace('_', '/'));

背景

Base64编码和Base64url编码是相同的,唯一的区别在于上述两个字符的替换。

请查看RFC 4648中的第1表和第2表:

                Table 1: The Base 64 Alphabet

 Value Encoding  Value Encoding  Value Encoding  Value Encoding
     0 A            17 R            34 i            51 z
     1 B            18 S            35 j            52 0
     2 C            19 T            36 k            53 1
     3 D            20 U            37 l            54 2
     4 E            21 V            38 m            55 3
     5 F            22 W            39 n            56 4
     6 G            23 X            40 o            57 5
     7 H            24 Y            41 p            58 6
     8 I            25 Z            42 q            59 7
     9 J            26 a            43 r            60 8
    10 K            27 b            44 s            61 9
    11 L            28 c            45 t            62 +
    12 M            29 d            46 u            63 /
    13 N            30 e            47 v
    14 O            31 f            48 w         (pad) =
    15 P            32 g            49 x
    16 Q            33 h            50 y

[...]

                Table 2: The "URL and Filename safe" Base 64 Alphabet

 Value Encoding  Value Encoding  Value Encoding  Value Encoding
     0 A            17 R            34 i            51 z
     1 B            18 S            35 j            52 0
     2 C            19 T            36 k            53 1
     3 D            20 U            37 l            54 2
     4 E            21 V            38 m            55 3
     5 F            22 W            39 n            56 4
     6 G            23 X            40 o            57 5
     7 H            24 Y            41 p            58 6
     8 I            25 Z            42 q            59 7
     9 J            26 a            43 r            60 8
    10 K            27 b            44 s            61 9
    11 L            28 c            45 t            62 - (minus)
    12 M            29 d            46 u            63 _
    13 N            30 e            47 v           (underline)
    14 O            31 f            48 w
    15 P            32 g            49 x
    16 Q            33 h            50 y         (pad) =

下面是RFC文件中的另一段引用:

这种编码可以称为"base64url"。应该不把这种编码看作与"base64"编码相同,并且不应仅仅称其为"base64"编码。除非另有说明,否则"base64"指的是上一部分中的base 64。这种编码在技术上与前一种编码完全相同,除了表2中所示的第62和第63字母表字符。


2
根据RFC 2045,表1:Base64字母表不包含-_。只有字母表中的字符才被Base64解码器使用,您不能解码任意字符。
                Table 1: The Base64 Alphabet

 Value Encoding  Value Encoding  Value Encoding  Value Encoding
     0 A            17 R            34 i            51 z
     1 B            18 S            35 j            52 0
     2 C            19 T            36 k            53 1
     3 D            20 U            37 l            54 2
     4 E            21 V            38 m            55 3
     5 F            22 W            39 n            56 4
     6 G            23 X            40 o            57 5
     7 H            24 Y            41 p            58 6
     8 I            25 Z            42 q            59 7
     9 J            26 a            43 r            60 8
    10 K            27 b            44 s            61 9
    11 L            28 c            45 t            62 +
    12 M            29 d            46 u            63 /
    13 N            30 e            47 v
    14 O            31 f            48 w         (pad) =
    15 P            32 g            49 x
    16 Q            33 h            50 y

正如Roland Illig所指出的那样,您可能正在处理URL友好的Base 64变体,其中_替换了+-替换了/。在这种情况下,在解码之前恢复更改可能就足够了:
String raw = new String(res.getBytes("s_id"));
String encoded = raw.replace("_", "+").replace("-", "/");
String decoded = Base64.getDecoder().decode(encoded);

然而,如果没有看到服务器端的编码代码,就无法确定数据实际上是如何编码的。


实际上,我是从服务器获取这些编码数据,只需要对其进行解码以达到某种目的。所以我无法控制编码字节数组中是否存在这些值。您能否建议我为了成功解码它们而采取的最佳方法? - abhishek ranjan
1
那么,要么你没有在服务器上使用Base64对数据进行编码,要么你读取数据的方式有误。弄清楚服务器上数据的确切编码方式,并使用正确的解码器。 - Karol Dowbecki
1
你的回答应该提到Base64的“URL友好”变体,它使用_和-代替+和/。 - Roland Illig

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