I had the opportunity to base64 encode / decode by embedding image data in JSON, so I will record the investigation as a memorandum.
I will quote this article because it was explained in an easy-to-understand manner. https://qiita.com/PlanetMeron/items/2905e2d0aa7fe46a36d4 The Base64 conversion algorithm is carefully described in an easy-to-understand manner for your reference.
Simply put ・ A-z (26 characters) ・ A-Z (26 characters) ・ 0-9 (10 characters) ・ + ・ / ・ = (Used as a padding character to the end to make the data length uniform) It seems that it is an encoding method expressed with a total of 65 characters. * The last "=" is a 64-character expression if padding is not required.
Binary data etc. can be converted to 64 (or 65) character strings so that special characters are not included in JSON, and data can be sent and received safely. Since it is expressed only with 64 (or 65) types of characters, it is also a feature that the amount of data increases by about 1.3 times (133%).
When Base64 encoding as the MIME format of e-mail, a line feed code (CRLF) is entered every 76 characters according to the MIME standard. Including these 2 bytes, the amount of data is about 137%.
The Base64 formats are classified into the following three patterns.
gu2CoIKigqSCpoKogqmCq4Ktgq+CsYKzgrWCt4K5gruCvYK/gsKCxILGgsiCyYLKgsuCzILNgtCC04LWgtmC3ILdgt6C34LggqCCoA==
・ The last 2 characters that are multiples of 4 are padding characters "=" ・ Includes +, / symbols (* If this is used in a URL, it will be subject to percent encoding)
gu2CoIKigqSCpoKogqmCq4Ktgq+CsYKzgrWCt4K5gruCvYK/gsKCxILGgsiCyYLKgsuCzILNgtCC
04LWgtmC3ILdgt6C34LggqCCoA==
・ The last 2 characters that are multiples of 4 are padding characters "=" ・ Includes +, / symbols (* If this is used in a URL, it will be subject to percent encoding)
gu2CoIKigqSCpoKogqmCq4Ktgq-CsYKzgrWCt4K5gruCvYK_gsKCxILGgsiCyYLKgsuCzILNgtCC04LWgtmC3ILdgt6C34LggqCCoA
-URL unsafe symbols have been converted. Remove "+" → "-", "/" → "_", "="
--Use base64 character string for image data so that special characters are not included in JSON etc. --Basic authentication uses a Base64-encoded character string with the user name and password separated by a colon (:). --Embed base64 encoded image as it is in html to reduce the number of requests when displaying a web page. -Widely used in e-mail that can only handle 7-bit data.
Java8~ Since Java8 or later, the utility of java.util.Base64 is provided in the JDK standard, so it seems good to use this. Java 8 or later has not been verified on the actual machine. This is a very simple and easy-to-understand code sample, so it was helpful. https://gist.github.com/komiya-atsushi/d878e6e4bf9ba6dae8fa
Java7 To handle Base64 with Java7 ...
--Use Apache Commons Codec --Use javax.mail (using JavaMail's MimeUtility) --Using Seasar2's Base64Util --Make your own
And so on. This time, I would like to base64 encode / decode using the top two "Apache Commons Codec" and "javax.mail" that I had at hand. The implementation here implements a sample that encodes / decodes binary data (byte []) into a Base64 string (String).
Apache Commons Codec Version: Validated with 1.11.
public static String encodeBase64(byte[] data) {
return Base64.encodeBase64String(data);
}
⇒ Base64 # encodeBase64String
is used.
public static String encodeBase64Chunked(byte[] data) {
byte[] encoded = Base64.encodeBase64Chunked(data);
return new String(encoded);
}
⇒ I am using Base64 # encodeBase64Chunked
.
An interface for adding a line feed code was prepared.
public static String encodeBase64URLSafe(byte[] data) {
return Base64.encodeBase64URLSafeString(data);
}
⇒ Base64 # encodeBase64URLSafeString
is used.
There was a dedicated interface for URL-Safe.
public static byte[] decodeBase64(String data) {
return Base64.decodeBase64(data);
}
⇒ It seems that decoding can be done uniformly with this.
javax.mail Version: Verified with 1.4.6
private static String trimCRLF(ByteArrayOutputStream encodedCRLF) {
byte inputArray[] = encodedCRLF.toByteArray();
byte outputArray[] = new byte[encodedCRLF.size()];
// CR(0x0d)、LF(0x0a)Skip the part and copy it to the output array
int n = 0;
for (int i = 0; i < encodedCRLF.size() - 1; i++) {
if (inputArray[i] == 0x0d) {// CR
if (inputArray[i + 1] == 0x0a) {// LF
i++;
continue;
}
}
outputArray[n] = inputArray[i];
n++;
}
return new String(outputArray, 0, n);
}
public static String encodeBase64(byte[] data) {
try (ByteArrayOutputStream encodedChunked = new ByteArrayOutputStream()) {
try (OutputStream os = MimeUtility.encode(encodedChunked, "base64")) {
os.write(data);
os.flush();
}
//Remove newline characters
String encodedStr = trimCRLF(encodedChunked);
return encodedStr;
} catch (IOException e) {
e.printStackTrace();
return "Bad Encryption";
} catch (MessagingException e) {
e.printStackTrace();
return "Bad Encryption";
}
}
⇒ In MimeUtility, it seems that you can encode with MimeUtility.encode, By default, it is in a MIME-based format that includes line breaks. Therefore, the line feed code is removed to eliminate line breaks.
public static String encodeBase64Chunked(byte[] data) {
try (ByteArrayOutputStream encodedChunked = new ByteArrayOutputStream()) {
try (OutputStream os = MimeUtility.encode(encodedChunked, "base64")) {
os.write(data);
os.flush();
}
return encodedChunked.toString();
} catch (IOException e) {
e.printStackTrace();
return "Bad Encryption";
} catch (MessagingException e) {
e.printStackTrace();
return "Bad Encryption";
}
}
⇒ I am using MimeUtility.encode.
private static String urlSafeEncode(ByteArrayOutputStream encodedCRLF) {
byte inputArray[] = encodedCRLF.toByteArray();
byte outputArray[] = new byte[encodedCRLF.size()];
// CR(0x0d)、LF(0x0a)Skip the part and copy it to the output array
int n = 0;
for (int i = 0; i < encodedCRLF.size() - 1; i++) {
if (inputArray[i] == 0x0d) {// CR
if (inputArray[i + 1] == 0x0a) {// LF
i++;
continue;
}
}
// URL-Convert to Safe
if (inputArray[i] == 0x2b) {// 「+」
outputArray[n] = 0x2d;// 「-」
}
else if (inputArray[i] == 0x2f) {// 「/」
outputArray[n] = 0x5f;// 「_」
}
else if (inputArray[i] == 0x3d) {// 「=」
continue;
}
else {
outputArray[n] = inputArray[i];
}
n++;
}
return new String(outputArray, 0, n);
}
public static String encodeBase64URLSafe(byte[] data) {
try (ByteArrayOutputStream encodedChunked = new ByteArrayOutputStream()) {
try (OutputStream os = MimeUtility.encode(encodedChunked, "base64")) {
os.write(data);
os.flush();
}
//URL with newline characters removed-Make it Safe
String encodedURLSafe = urlSafeEncode(encodedChunked);
return encodedURLSafe;
} catch (IOException e) {
e.printStackTrace();
return "Bad Encryption";
} catch (MessagingException e) {
e.printStackTrace();
return "Bad Encryption";
}
⇒ In order to make URL-Safe, the symbols "+", "/" and "=" are converted in addition to the line feed code removal. It's very long. ..
public static byte[] decodeBase64(String data) {
byte[] urlsafe = data.getBytes();
int mod = urlsafe.length % 4;
byte[] nosafe = new byte[urlsafe.length + mod];
for (int i = 0; i < urlsafe.length; i++) {
if (urlsafe[i] == 0x2d) {// 「-」
nosafe[i] = 0x2b;// 「+」
}
else if (urlsafe[i] == 0x5f) {// 「_」
nosafe[i] = 0x2f;// 「/」
}
else {
nosafe[i] = urlsafe[i];
}
}
//Those that are less than a multiple of the fixed length 4=Padding with
for (int i = urlsafe.length + mod - 1; i >= urlsafe.length; i--) {
nosafe[i] = 0x3d;// 「=」
}
ByteArrayInputStream from = new ByteArrayInputStream(nosafe);
try (InputStream is = MimeUtility.decode(from, "base64"); ByteArrayOutputStream to = new ByteArrayOutputStream()) {
byte[] buf = new byte[8192];
int readCnt;
while ((readCnt = is.read(buf)) != -1) {
to.write(buf, 0, readCnt);
}
to.flush();
return to.toByteArray();
} catch (MessagingException | IOException e) {
e.printStackTrace();
return "Bad Decryption".getBytes();
}
}
⇒ It is forcible. .. In the decoding process, it is converted back to URL-UnSafe on the assumption that the converted character string will be entered in URL-Safe. After padding with "=" according to the number of digits to a multiple of 4, MimeUtility.decode is used for decoding. I don't think I usually write this kind of code.
--There are three main types of Base64: "basic format", "MIME standard format including line feed code", and "URL-Safe converted format". --For Java 8 or later, use the standard java.util.Base64 class. --Apache Commons Codec is easy to use in Java 7. If you can't use it, use javax.mail.
that's all.
Recommended Posts