JavaでBase64エンコードしてJavaScriptでBase64デコードしてみたよ!

JavaでBase64エンコードしてJavaScriptでBase64デコードする方法がネットで検索しても出てこなかったので今回自力で実装してみました。

気になる方は最後まで是非見ていって下さいね。

Base64とは?

Base64とは「英数字しか扱うことができない通信環境でマルチバイト文字やバイナリデータを扱うためのエンコード方式」です。7ビットのデータしか扱うことができない電子メールで広く利用されています。

ここで言う英数字とは、「A-Z、a-z、0-9」の62種類の文字と「+、/」の2種類の記号、余った文字を詰める(パディング)ために必要な「=」の合計64種類+1の文字のことを言います。

Wikipediaを参考にさせて頂きました。
https://ja.wikipedia.org/wiki/Base64

バイナリデータも扱えるため画像データやドキュメントデータなどもエンコードできます。(電子メールで使われているので添付ファイルという形で頻繁に使われていますね。)

実際に実装してみよう

JavaでBase64エンコード

Base64エンコード・デコード用にBase64クラスが用意されているのでこちらを使っています。

3種類のデータ(2バイト文字、機種依存文字、サロゲートペア文字)をBase64エンコードして結果を出力しています。

package com.base64test;

import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Base64;
import java.util.List;

public class Base64Test {

    public static void main(String[] args) {
        // 元の文字列
        List<String> originalStrs = Arrays.asList(
                // 2バイト文字
                "むかしむかし、あるところに、おじいさんとおばあさんが住んでいました。<br>"
                + "おじいさんは山へしばかりに、おばあさんは川へせんたくに行きました。<br>"
                + "おばあさんが川でせんたくをしていると、ドンブラコ、ドンブラコと、大きな桃が流れてきました。",
                // 機種依存文字
                "①②③④⑤⑥⑦➇⑨⑩(←機種依存文字)",
                // サロゲートペア文字
                "𣜿𣝣𣳾𤟱𥒎𥔎𥝱𥧄𥶡𦫿(←サロゲートペア文字)"
        );

        originalStrs.stream()
            // Base64へのエンコード
            .map(s -> Base64.getEncoder().encodeToString(s.getBytes(StandardCharsets.UTF_8)))
            // エンコードされた文字列の出力
            .forEach(System.out::println);
    }

}

JavaScriptでBase64デコード

Base64エンコードされた文字列をBase64デコードする関数(fromBinary)を宣言しています。

この関数の中で使われている atob 関数は元の文字列が英数字の場合のみしかBase64デコードできない(2バイト文字つまり日本語だとエラーになる)ため atob 関数でBase64デコードした文字列を一旦バイト配列に変えてから TextDecoder クラスでさらにバイト配列から文字列にデコードしています。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>Base64デコード</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<style>
    .box {
        width: 800px;
        word-wrap: break-word;
    }
</style>
</head>
<body>
    <h1>デコード前</h1>
    <div id="encoded" class="box"></div>
    <h1>デコード後</h1>
    <div id="decoded" class="box"></div>
<script>
    $(function(){
        const encodeds = [
            '44KA44GL44GX44KA44GL44GX44CB44GC44KL44Go44GT44KN44Gr44CB44GK44GY44GE44GV44KT44Go44GK44Gw44GC44GV44KT44GM5L2P44KT44Gn44GE44G+44GX44Gf44CCPGJyPuOBiuOBmOOBhOOBleOCk+OBr+WxseOBuOOBl+OBsOOBi+OCiuOBq+OAgeOBiuOBsOOBguOBleOCk+OBr+W3neOBuOOBm+OCk+OBn+OBj+OBq+ihjOOBjeOBvuOBl+OBn+OAgjxicj7jgYrjgbDjgYLjgZXjgpPjgYzlt53jgafjgZvjgpPjgZ/jgY/jgpLjgZfjgabjgYTjgovjgajjgIHjg4njg7Pjg5bjg6njgrPjgIHjg4njg7Pjg5bjg6njgrPjgajjgIHlpKfjgY3jgarmoYPjgYzmtYHjgozjgabjgY3jgb7jgZfjgZ/jgII=',
            '4pGg4pGh4pGi4pGj4pGk4pGl4pGm4p6H4pGo4pGp77yI4oaQ5qmf56iu5L6d5a2Y5paH5a2X77yJ',
            '8KOcv/CjnaPwo7O+8KSfsfClko7wpZSO8KWdsfClp4Twpbah8Karv++8iOKGkOOCteODreOCsuODvOODiOODmuOCouaWh+Wtl++8iQ=='
        ];

        decodeds = encodeds.map(s => fromBinary(s));

        $('#encoded').html(encodeds.join('<br><br>'));
        $('#decoded').html(decodeds.join('<br><br>'));
    });

    function fromBinary(encoded) {
        const binary = atob(encoded);
        const bytes = new Uint8Array(binary.length);
        for (let i = 0; i < bytes.length; i++) {
            bytes[i] = binary.charCodeAt(i);
        }
        return new TextDecoder("utf-8").decode(new Uint8Array(bytes.buffer));
    }
</script>
</body>
</html>

参考サイト

本実装をするにあたり下記サイトを参考にさせて頂きました。

https://stackoverflow.com/questions/30106476/using-javascripts-atob-to-decode-base64-doesnt-properly-decode-utf-8-strings

実装結果

デコード前とデコード後を比較した文字列を表示すると以下の通りになります。

まとめ

JavaでBase64エンコードしてJavaScriptでBase64デコードすると言う、全く違う言語間でも連携ができるということをお分かり頂けたでしょうか?

元の文字列をBase64エンコードしておけば解読するのは難しいのでその辺りのことを利用してクイズの答えを正解表示時のみデコードするとか使い道は色々と考えられそうです。

最後までお読み頂きありがとうございました。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です