net.freeutils.util.Base64 Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jelementary Show documentation
Show all versions of jelementary Show documentation
The Java Elementary Utilities package
The newest version!
/*
* Copyright © 2003-2024 Amichai Rothman
*
* This file is part of JElementary - the Java Elementary Utilities package.
*
* JElementary is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* JElementary is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with JElementary. If not, see .
*
* For additional info see https://www.freeutils.net/source/jelementary/
*/
package net.freeutils.util;
import java.io.UnsupportedEncodingException;
/**
* The {@code Base64} class contains RFC 4648 compliant base64 and base64url
* encoding and decoding methods.
*/
public class Base64 {
protected static final byte[] ENCODE, DECODE, ENCODE_URL, DECODE_URL;
static {
byte[][] tables = createLookupTables("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");
ENCODE = tables[0];
DECODE = tables[1];
tables = createLookupTables("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_");
ENCODE_URL = tables[0];
DECODE_URL = tables[1];
}
/**
* Creates an encode/decode lookup table pair using the given encoding characters.
*
* @param table a string containing the ordered characters used as the encoding lookup table
* @return an array containing the two lookup arrays, for encoding and decoding (respectively)
*/
public static byte[][] createLookupTables(String table) {
byte[] enc = new byte[table.length()];
byte[] dec = new byte[256];
for (int i = 0; i < dec.length; i++)
dec[i] = -1;
for (int i = 0; i < enc.length; i++) {
enc[i] = (byte)table.charAt(i);
dec[enc[i]] = (byte)i;
}
return new byte[][] { enc, dec };
}
/**
* Encodes the given bytes using the given encoding lookup table.
*
* @param b the bytes to encode
* @param lookup the encoding lookup table
* @return the encoded bytes
*/
public static byte[] encode(byte[] b, byte[] lookup) {
int full = b.length / 3 * 3;
int rem = b.length - full;
byte[] out = new byte[(b.length + 2) / 3 * 4];
int i = 0;
int j = 0;
// encode full byte triplets
while (i < full) {
int t = (b[i++] & 0xFF) << 16 | (b[i++] & 0xFF) << 8 | (b[i++] & 0xFF);
out[j++] = lookup[t >> 18];
out[j++] = lookup[(t >> 12) & 0x3F];
out[j++] = lookup[(t >> 6) & 0x3F];
out[j++] = lookup[t & 0x3F];
}
// encode remainder (0, 1 or 2 last bytes)
if (rem > 0) {
int t = (b[i++] & 0xFF) << 16 | (rem == 1 ? 0 : (b[i] & 0xFF) << 8);
out[j++] = lookup[t >> 18];
out[j++] = lookup[(t >> 12) & 0x3F];
out[j++] = rem == 1 ? (byte)'=' : lookup[(t >> 6) & 0x3F];
out[j] = '=';
}
return out;
}
/**
* Decodes the given bytes using the given decoding lookup table.
*
* @param b the bytes to decode
* @param lookup the decoding lookup table
* @return the decoded bytes
*/
public static byte[] decode(byte[] b, byte[] lookup) {
int pad = 0;
for (int i = b.length - 1; i >= 0 && b[i] == '='; i--)
pad++;
int full = (b.length - pad) / 4 * 4;
byte[] out = new byte[b.length / 4 * 3 - pad];
int i = 0;
int j = 0;
// decode full byte quads
while (i < full) {
int t = lookup[b[i++]] << 18 | lookup[b[i++]] << 12 | lookup[b[i++]] << 6 | lookup[b[i++]];
out[j++] = (byte)(t >> 16);
out[j++] = (byte)(t >> 8);
out[j++] = (byte)t;
}
// decode remainder (0, 1 or 2 last bytes)
if (pad > 0) {
int t = lookup[b[i++]] << 18 | lookup[b[i++]] << 12 | (pad == 1 ? lookup[b[i]] << 6 : 0);
out[j++] = (byte)(t >> 16);
if (pad == 1)
out[j] = (byte)(t >> 8);
}
return out;
}
/**
* Checks whether the given bytes are validly encoded.
*
* @param b the bytes to check
* @param lookup the decoding lookup table
* @return true if the bytes are validly encoded, false otherwise
*/
public static boolean isValid(byte[] b, byte[] lookup) {
int len = b.length;
if (len % 4 != 0)
return false;
for (int i = 0; i < len; i++)
if (lookup[b[i]] < 0 && (i < len - 2 || b[i] != '=' || b[len - 1] != '='))
return false;
return true;
}
/**
* Encodes the given bytes using standard base64 encoding.
*
* @param b the bytes to encode
* @return the encoded bytes
*/
public static byte[] encode(byte[] b) {
return encode(b, ENCODE);
}
/**
* Encodes the given bytes using standard base64url encoding.
*
* @param b the bytes to encode
* @return the encoded bytes
*/
public static byte[] encodeUrl(byte[] b) {
return encode(b, ENCODE_URL);
}
/**
* Decodes the given bytes using standard base64 decoding.
* The input it assumed to be valid, as this method does not
* validate that it is indeed legal base64-encoded data.
*
* @param b the bytes to decode
* @return the decoded bytes
*/
public static byte[] decode(byte[] b) {
return decode(b, DECODE);
}
/**
* Decodes the given bytes using standard base64url decoding.
* The input it assumed to be valid, as this method does not
* validate that it is indeed legal base64-encoded data.
*
* @param b the bytes to decode
* @return the decoded bytes
*/
public static byte[] decodeUrl(byte[] b) {
return decode(b, DECODE_URL);
}
/**
* Checks whether the given bytes are validly encoded in standard base64 encoding.
*
* @param b the bytes to check
* @return true if the bytes are validly encoded, false otherwise
*/
public static boolean isValid(byte[] b) {
return isValid(b, DECODE);
}
/**
* Checks whether the given bytes are validly encoded in standard base64url encoding.
*
* @param b the bytes to check
* @return true if the bytes are validly encoded, false otherwise
*/
public static boolean isValidUrl(byte[] b) {
return isValid(b, DECODE_URL);
}
/**
* Decodes the given string using standard base64 decoding.
*
* @param s the string to decode
* @param validate if true, the bytes are validated to be legal base64 bytes
* @return the decoded bytes
* @throws IllegalArgumentException if the given string contains non US-ASCII characters,
* or if validate is true and the given bytes are not valid base64 bytes
*/
public static byte[] decode(String s, boolean validate) {
return decode(Strings.getASCIIBytes(s), validate);
}
/**
* Decodes the given string using standard base64url decoding.
*
* @param s the string to decode
* @param validate if true, the bytes are validated to be legal base64url bytes
* @return the decoded bytes
* @throws IllegalArgumentException if the given string contains non US-ASCII characters,
* or if validate is true and the given bytes are not valid base64url bytes
*/
public static byte[] decodeUrl(String s, boolean validate) {
return decodeUrl(Strings.getASCIIBytes(s), validate);
}
/**
* Decodes the given bytes using standard base64 decoding.
*
* @param b the bytes to decode
* @param validate if true, the bytes are validated to be legal base64 bytes
* @return the decoded bytes
* @throws IllegalArgumentException if validate is true and the given
* bytes are not valid base64 bytes
*/
public static byte[] decode(byte[] b, boolean validate) {
if (validate && !isValid(b))
throw new IllegalArgumentException("invalid base64 bytes");
return decode(b);
}
/**
* Decodes the given bytes using standard base64url decoding.
*
* @param b the bytes to decode
* @param validate if true, the bytes are validated to be legal base64url bytes
* @return the decoded bytes
* @throws IllegalArgumentException if validate is true and the given
* bytes are not valid base64url bytes
*/
public static byte[] decodeUrl(byte[] b, boolean validate) {
if (validate && !isValidUrl(b))
throw new IllegalArgumentException("invalid base64url bytes");
return decodeUrl(b);
}
/**
* Encodes the given bytes using standard base64 encoding.
*
* @param b the bytes to encode
* @return the encoded bytes as an ASCII hex string
*/
public static String encodeString(byte[] b) {
try {
return new String(encode(b, ENCODE), "US-ASCII");
} catch (UnsupportedEncodingException uee) {
return null; // can't happen
}
}
/**
* Encodes the given bytes using standard base64url encoding.
*
* @param b the bytes to encode
* @return the encoded bytes as an ASCII hex string
*/
public static String encodeStringUrl(byte[] b) {
try {
return new String(encode(b, ENCODE_URL), "US-ASCII");
} catch (UnsupportedEncodingException uee) {
return null; // can't happen
}
}
/**
* Encodes the given string as UTF-8 bytes using standard base64 encoding.
*
* @param s the string to encode
* @return the encoded bytes as an ASCII hex string
*/
public static String encodeUTFString(String s) {
try {
return new String(encode(s.getBytes("UTF-8"), ENCODE), "US-ASCII");
} catch (UnsupportedEncodingException uee) {
return null; // can't happen
}
}
/**
* Encodes the given string as UTF-8 bytes using standard base64url encoding.
*
* @param s the string to encode
* @return the encoded bytes as an ASCII hex string
*/
public static String encodeUTFStringUrl(String s) {
try {
return new String(encode(s.getBytes("UTF-8"), ENCODE_URL), "US-ASCII");
} catch (UnsupportedEncodingException uee) {
return null; // can't happen
}
}
/**
* Decodes the given string using standard base64 decoding.
*
* @param s the string to decode
* @param validate if true, the bytes are validated to be legal base64 bytes
* @param charset the charset to interpret the decoded bytes in
* @return the decoded bytes as string in the given charset
* @throws IllegalArgumentException if the given string contains non US-ASCII characters,
* or if validate is true and the given bytes are not valid base64 bytes,
* or if the decoded bytes are invalid in the given charset,
* or if the given charset does not exist
*/
public static String decodeString(String s, boolean validate, String charset) {
try {
return new String(decode(Strings.getASCIIBytes(s), validate), charset);
} catch (UnsupportedEncodingException uee) {
throw new IllegalArgumentException(uee);
}
}
/**
* Decodes the given string using standard base64url decoding.
*
* @param s the string to decode
* @param validate if true, the bytes are validated to be legal base64url bytes
* @param charset the charset to interpret the decoded bytes in
* @return the decoded bytes as string in the given charset
* @throws IllegalArgumentException if the given string contains non US-ASCII characters,
* or if validate is true and the given bytes are not valid base64url bytes,
* or if the decoded bytes are invalid in the given charset,
* or if the given charset does not exist
*/
public static String decodeStringUrl(String s, boolean validate, String charset) {
try {
return new String(decodeUrl(Strings.getASCIIBytes(s), validate), charset);
} catch (UnsupportedEncodingException uee) {
throw new IllegalArgumentException(uee);
}
}
/**
* Decodes the given string using standard base64 decoding.
*
* @param s the string to decode
* @param validate if true, the bytes are validated to be legal base64 bytes
* @return the decoded bytes as string in the given charset
* @throws IllegalArgumentException if the given string contains non US-ASCII characters,
* or if validate is true and the given bytes are not valid base64 bytes,
* or if the decoded bytes are invalid in the UTF-8 charset
*/
public static String decodeUTFString(String s, boolean validate) {
return decodeString(s, validate, "UTF-8");
}
/**
* Decodes the given string using standard base64url decoding.
*
* @param s the string to decode
* @param validate if true, the bytes are validated to be legal base64url bytes
* @return the decoded bytes as string in the given charset
* @throws IllegalArgumentException if the given string contains non US-ASCII characters,
* or if validate is true and the given bytes are not valid base64url bytes,
* or if the decoded bytes are invalid in the UTF-8 charset
*/
public static String decodeUTFStringUrl(String s, boolean validate) {
return decodeStringUrl(s, validate, "UTF-8");
}
/**
* Decodes the given string using standard base64 decoding.
*
* @param s the string to decode
* @param validate if true, the bytes are validated to be legal base64 bytes
* @return the decoded bytes as string in the ISO-8869-1 charset
* @throws IllegalArgumentException if the given string contains non US-ASCII characters,
* or if validate is true and the given bytes are not valid base64 bytes
*/
public static String decodeString(String s, boolean validate) {
return decodeString(s, validate, "ISO8859_1");
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy