跳到主要内容
ecdsa.com
Java (JDK)Java

错误信息

java.lang.IllegalArgumentException: Illegal base64 character 2d

也可能输出为

  • java.lang.IllegalArgumentException: Illegal base64 character a
  • java.lang.IllegalArgumentException: Illegal base64 character d
  • java.lang.IllegalArgumentException: Illegal base64 character 5f
  • java.lang.IllegalArgumentException: Illegal base64 character 20

这个十六进制值指出了出问题的字符:`2d` 是“-”,`5f` 是“_”,`a` 是 LF,`d` 是 CR,`20` 是空格。

Java (JDK) — java.util.Base64.Decoder.decode

含义

`Base64.getDecoder()` 是严格的 RFC 4648 解码器:它只接受 `A–Z a–z 0–9 + /` 和 `=` 填充,遇到第一个其他字符就停止。那个十六进制数就是该字符的编码:`2d` 是 `-`(`-----BEGIN …-----` 中的短横线,或 base64url 字母表中的字符),`a` 是换行符,`d` 是回车符,`20` 是空格,`5f` 是下划线。数据本身通常没有问题——只是它的文本包装方式与这个解码器要求的不一样。

原因

修复方法

  1. 1.

    去掉封装行,并使用 MIME 解码器

    `Base64.getMimeDecoder()` 会跳过行分隔符,这正是 PEM 正文所需要的。

    java
    String body = pem.replaceAll("-----(BEGIN|END) [A-Z ]+-----", "");
    byte[] der = Base64.getMimeDecoder().decode(body); // ignores line separators and other non-alphabet characters
  2. 2.

    JOSE 数据使用 URL 解码器

    JWT 和 JWK 中的所有内容都是 base64url;URL 解码器也接受省略了填充的数据。

    java
    // JWT segments and JWK fields ("x", "y", "n", "e") use base64url without padding.
    byte[] header = Base64.getUrlDecoder().decode(jwt.split("\\.")[0]);
    byte[] x = Base64.getUrlDecoder().decode(jwk.get("x"));

相关错误

浏览完整的签名错误库