NationalSecurityAgency/ghidra · error · NumberFormatException
Bad base64 encoding
Error message
Bad base64 encoding
What it means
Thrown by Base64Lite.decodeLongBase64 when a character in the input string maps to a negative value in the decode table, i.e. it is not one of the 64 valid RFC-4648 URL/filename-safe characters (A-Z, a-z, 0-9, '-', '_'). It is an unchecked NumberFormatException. This is the BSim-internal base64 used for compact long encodings (e.g. signature ids), not standard MIME base64.
Source
Thrown at Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/elastic/Base64Lite.java:114
else {
buffer[pos++] = encode[chunk];
seenNonZero = true;
}
}
return new String(buffer,0,pos);
}
/**
* Decode (up to 11) base64 characters to produce a long
* @param val is the String to decode
* @return the decode long
*/
public static long decodeLongBase64(String val) {
long res = 0;
for(int i=0;i<val.length();++i) {
int chunk = decode[val.charAt(i)];
if (chunk < 0)
throw new NumberFormatException("Bad base64 encoding");
res <<= 6;
res |= chunk;
}
return res;
}
}
View on GitHub (pinned to d5f144c24d)
Solutions
- Ensure the value was produced by Base64Lite.encodeLongBase64 (URL-safe alphabet, no padding).
- Strip whitespace/newlines and remove any '=' padding before decoding.
- If the source is standard base64, translate '+'->'-' and '/'->'_' before passing to decodeLongBase64.
- Limit input to <=11 characters and verify every char is in the URL-safe alphabet.
Example fix
// before
long v = Base64Lite.decodeLongBase64(s); // throws on '+' / '/' / '='
// after
String safe = s.replace('+', '-').replace('/', '_').replaceAll("[=\\s]", "");
long v = Base64Lite.decodeLongBase64(safe); Defensive patterns
Strategy: validation
Validate before calling
private static final String SAFE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
boolean isBase64Lite(String s) {
for (int i = 0; i < s.length(); i++) if (SAFE.indexOf(s.charAt(i)) < 0) return false;
return s.length() <= 11;
}
if (!isBase64Lite(val)) throw new NumberFormatException("not Base64Lite: " + val);
long v = Base64Lite.decodeLongBase64(val); Type guard
boolean isBase64LiteSafe(String s) {
if (s == null || s.length() > 11) return false;
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (!((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '-' || c == '_')) return false;
}
return true;
} Try / catch
try {
return Base64Lite.decodeLongBase64(val);
} catch (NumberFormatException e) {
String safe = val.replace('+', '-').replace('/', '_').replaceAll("[=\\s]", "");
return Base64Lite.decodeLongBase64(safe);
} Prevention
- Only decode values produced by Base64Lite.encodeLongBase64.
- Strip whitespace/newlines and '=' padding before decoding.
- Map '+'->'-' and '/'->'_' if the source uses standard base64.
When it happens
Trigger: Calling decodeLongBase64(val) with a string containing standard base64 characters like '+' or '/', whitespace, '=' padding, or any char outside the 0-127 ASCII range / not in the encode alphabet. Reached when decoding stored signature/hash longs from an elastic or XML source.
Common situations: Data encoded with a standard (MIME) base64 encoder instead of Base64Lite; '+' or '/' characters present; stray whitespace/newlines or '=' padding not stripped; truncated or corrupted field; mixing Base64Lite output with another base64 variant.
Related errors
- connection.getResponseMessage()
- {type} : {reason}
- Error parsing URL: {message}
- Error sending request: {message}
- Error parsing response: {message}
AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14).
Data as JSON: /api/errors/5ed31ddaa6135c16.
Report an issue: GitHub.