Mensaje de error
java.lang.IllegalArgumentException: Illegal base64 character 2d
También se muestra 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
El valor hexadecimal identifica el carácter problemático: `2d` «-», `5f` «_», `a` LF, `d` CR, `20` espacio.
Java (JDK) — java.util.Base64.Decoder.decode
Qué significa
`Base64.getDecoder()` es el decodificador estricto del RFC 4648: solo acepta `A–Z a–z 0–9 + /` y el relleno `=`, y se detiene en el primer carácter distinto. El número hexadecimal es el código de ese carácter: `2d` es `-` (los guiones de `-----BEGIN …-----`, o el guion del alfabeto base64url), `a` es un salto de línea, `d` un retorno de carro, `20` un espacio y `5f` un guion bajo. Normalmente los datos están bien: solo vienen en un envoltorio textual distinto del que espera el decodificador.
Por qué ocurre
No se quitaron el encabezado y el pie del PEM (2d)
frecuenteAl decodificar el archivo PEM entero se llega al primer `-` de `-----BEGIN`. Solo el cuerpo entre las líneas delimitadoras está en base64.
Saltos de línea dentro del cuerpo (a o d)
frecuentePEM corta el base64 en líneas de 64 caracteres. El decodificador básico rechaza el salto de línea; los archivos editados en Windows añaden además `\r`.
Datos base64url pasados al decodificador básico (2d o 5f)
frecuenteLos segmentos de un JWT y las coordenadas de una JWK usan `-` y `_` en lugar de `+` y `/`. Necesitan `Base64.getUrlDecoder()`.
Espacios o comillas de la configuración (20, 22)
ocasionalLas claves pegadas en YAML, en archivos de propiedades o en variables de entorno pueden arrastrar espacios, comillas o secuencias `\n` escapadas.
Cómo solucionarlo
- 1.
Quitar los delimitadores y usar el decodificador MIME
`Base64.getMimeDecoder()` omite los separadores de línea, que es justo lo que necesita el cuerpo de un 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.
Usar el decodificador URL para datos JOSE
Todo lo que hay en un JWT y en una JWK está en base64url; el decodificador URL acepta además la falta de relleno.
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"));