【问题标题】:Error while decoding a byte array to base64 which contains characters like '-' and '_'将字节数组解码为 base64 时出错,其中包含“-”和“_”等字符
【发布时间】:2019-03-08 14:31:38
【问题描述】:

我正在尝试对字节数组进行 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 之后的代码差异。 这些代码是什么。无论我的代码中的这些字符如何,我如何解码任何值?

这是我的代码 sn-p:

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();
      }
   }

}

【问题讨论】:

    标签: java encoding base64 decode


    【解决方案1】:

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

    但是,如果不查看服务器端编码代码,就无法知道数据的实际编码方式。

    【讨论】:

    • 实际上我是从服务器获取这些编码数据,我只需要出于某种目的对其进行解码。所以我无法控制这些值在编码字节数组中的存在。您能否建议为了成功解码,最好的方法是什么?
    • 那么你要么没有在服务器上使用Base64 来编码数据,要么你读错了。弄清楚数据在服务器上的编码方式并使用正确的解码器。
    • 您的答案应该提到 Base64 的“URL 友好”变体,它使用 _ 和 - 而不是 + 和 /。
    【解决方案2】:

    解决方案

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

    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:nd 和 63:rd 字母字符,如表 2 所示。

    【讨论】:

      猜你喜欢
      • 2017-01-05
      • 1970-01-01
      • 2023-02-14
      • 2019-06-15
      • 1970-01-01
      • 1970-01-01
      • 2013-01-12
      • 2019-10-12
      • 1970-01-01
      相关资源
      最近更新 更多