将字节数组解码为包含'-'和'_'

时间:2018-10-03 11:06:58

标签: java encoding base64 decode

我正在尝试对字节数组进行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 个答案:

答案 0 :(得分:0)

根据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);

但是,如果不查看服务器端编码代码,就无法说出数据是如何实际编码的。

答案 1 :(得分:0)

解决方案

'-'替换为'+',将'_'替换为'/',如下行所示

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。      该编码在技术上与上一个相同,除了      表62中所示的62:nd和63:rd字母字符。