Mensagem de erro
java.lang.IllegalArgumentException: Illegal base64 character 2d
Também aparece como
- 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
O valor hexadecimal identifica o caractere problemático: `2d` “-”, `5f` “_”, `a` LF, `d` CR, `20` espaço.
Java (JDK) — java.util.Base64.Decoder.decode
O que significa
O `Base64.getDecoder()` é o decodificador estrito da RFC 4648: aceita apenas `A–Z a–z 0–9 + /` e o padding `=`, e para no primeiro caractere fora desse conjunto. O número hexadecimal é o código desse caractere: `2d` é `-` (os hifens de `-----BEGIN …-----` ou do alfabeto base64url), `a` é um avanço de linha, `d` um retorno de carro, `20` um espaço, `5f` um sublinhado. Em geral os dados estão corretos — só estão em um invólucro textual diferente do que o decodificador espera.
Por que acontece
O cabeçalho e o rodapé do PEM não foram removidos (2d)
comumA decodificação do arquivo PEM inteiro esbarra no primeiro `-` de `-----BEGIN`. Só o corpo entre as linhas delimitadoras é base64.
Quebras de linha dentro do corpo (a ou d)
comumO PEM quebra o base64 a cada 64 caracteres. O decodificador básico rejeita a quebra de linha; arquivos editados no Windows ainda acrescentam `\r`.
Dados base64url passados ao decodificador básico (2d ou 5f)
comumSegmentos de JWT e coordenadas de JWK usam `-` e `_` em vez de `+` e `/`. Esses dados exigem `Base64.getUrlDecoder()`.
Espaços ou aspas vindos da configuração (20, 22)
ocasionalChaves coladas em YAML, arquivos de propriedades ou variáveis de ambiente podem ganhar espaços, aspas ou sequências `\n` escapadas.
Como corrigir
- 1.
Remover as linhas delimitadoras e usar o decodificador MIME
O `Base64.getMimeDecoder()` ignora os separadores de linha — exatamente o que o corpo de um PEM exige.
java String body = pem.replaceAll("-----(BEGIN|END) [A-Z ]+-----", ""); byte[] der = Base64.getMimeDecoder().decode(body); // ignores line separators and other non-alphabet characters - 2.
Usar o decodificador de URL para dados JOSE
Tudo em um JWT e em uma JWK é base64url; o decodificador de URL também aceita a ausência de padding.
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"));