base64エンコードのアルゴリズムをRubyで実装する
Base64とは英数字、記号を用いてマルチバイト文字やバイナリデータ(画像など)を扱うためのエンコード方式です。
具体的にはA–Z, a–z, 0–9
までの62文字と、記号2つ (+
,/
)、さらにパディング(余った部分を詰める)のための記号として =
が用いられます。
7ビットの文字コードしか扱うことができない電子メールにおいてよく利用されています。
変換アルゴリズム
変換アルゴリズムは以下となります。
- 元データを6ビットずつに分割する(6ビットに満たない部分は0を追加して6ビットにする)。
- 各6ビットの値を変換表を使って4文字ずつに変換する(4文字に満たない部分は
=
記号を使って4文字にする)。
変換例
1. 元データ
文字列: “ABCDEFG”
2進数に変換する: “0100 0001 0100 0010 0100 0011 0100 0100 0100 0101 0100 0110 0100 0111”
rubyでのサンプルコード
1 | "ABCDEFG".unpack("B*").pop.scan(/.{1,4}/).join(" ") |
2. 6ビットずつに分割
“010000 010100 001001 000011 010001 000100 010101 000110 010001 11”
1 | "ABCDEFG".unpack("B*").pop.scan(/.{1,6}/).join(" ") |
3. 2ビット余るので、4ビット分0を追加して6ビットにする
“010000 010100 001001 000011 010001 000100 010101 000110 010001 110000”
1 | list = "ABCDEFG".unpack("B*").pop.scan(/.{1,6}/).join(" ").split.map { |s| sprintf("%-06s", s).gsub(" ", "0")}.join(" ") |
4. 変換表により、4文字ずつ変換
“QUJD”, “REVG”, “Rw”
1 | # 変換表を作成する |
5. 2文字余るので、2文字分 = 記号を追加して4文字にする
1 | base64_list.map {|s| sprintf("%-4s", s).gsub(" ", "=")} |
6. Base64文字列
“QUJDREVGRw==”
1 | base64_str.scan(/.{1,4}/).map {|s| sprintf("%-4s", s).gsub(" ", "=")}.join |
簡易的なbase64_decodeメソッド
今までのロジックをメソッドにまとめて簡易的なbase64_decodeメソッドを作成しました。
1 | class Base64 |
RubyのBase64ライブラリでencodeした値と比べてみましょう。
1 | require 'base64' |
Rubyのencode64は最後に改行が入るようですが、encodeされた値は同じですね!