セキュリティ基礎コース2/8
Base64について
こちらでは、Base64について解説します。
Base64は、64種類の文字を用いてバイナリデータを文字列に変換(エンコード)する方式のひとつです。この”Base”は、底(てい)を意味しており、他にもBase16やBase32などがあります。
※「底」の意味に関しましては後ほど触れますので、今は分からなくても構いません。
Base64が誕生する以前は、電子メールではASCIIコード表に含まれるアルファベットしか使えませんでした。そのため、それ以外の英数字や画像などを扱うためにMIMEという標準規格が利用されるようになりました。MIMEではメールを介してバイナリデータをやりとりするために、Base64を使ってエンコード/デコードを行います。
他にも、Basic認証というユーザー認証方式やファイルのアップロードなど、身近なところで使われている技術ですので、基本的な知識からしっかりと学んでいきましょう!
※ Basic認証は、最も簡単なユーザー認証の方式です。Authorizationヘッダを利用する場合に、ユーザー名とパスワードをBase64でエンコードします。
バイナリとは
まずはコンピュータの世界でどのようにデータを表現しているのかについて学ぶ必要があります。
バイナリ(binary)とは、日本語で「2進数」のことです。2進数とは、0と1のみで表す数字の記法です。黒い画面に無数の0と1の羅列(matrix)が表示されてる画像や映像を目にしたことがあるかもしれませんが、まさにそのようなイメージです!
普段わたしたちは、10進数の数字を扱うことがほとんどです。しかし、コンピュータの世界ではわたしたちの扱う文字や数字、記号といった全てのデータが0と1、つまり2進数(バイナリ)に変換されて扱われます。
※ちなみにこれは余談ですが、10進数は英語で「デシマル(decimal)」と言い、16進数は6を表す「ヘキサ(hexa)」と合体してヘキサデシマル(hexadecimal)やHEXと表記されます。
また、バイナリで表されるデータは、バイナリデータと言います。
2進数と10進数
バイナリについてざっくりとご説明しましたが、まだ腑に落ちない点が多いかと思います。
つづいては、2進数(バイナリ)と10進数の対応関係について解説します。
10進数では、10になったら一の位から十の位に上がり、さらに100になったら百の位へ上がり・・・というようになっています。つまりこの時、ひとつの位には0~9の10個の数字が入り、10になるときに次の位に上がります。
ちなみに、一の位は10の0乗(10^0=1)、十の位は10の1乗(10^1=10)、百の位は10の2乗(10^2=10×10=100)というように「10の累乗の指数が 1 ずつ増えていくたびに位がひとつ上がる」という法則性が分かりますね。
※ 累乗とは、同じ数(底)を何度もかけあわせることです。
※ 累乗の指数とは、底の右上に付いている数字のことで、底をかけあわせる回数を表している数字です。数学では^指数
というように表記します。たとえば、10の4乗(10^4)であれば、4が累乗の指数にあたり、これは「10を4回かけあわせる(10×10×10×10)」という意味になります。また、この場合の10のことを底と言います。
それでは、一方の2進数はどうでしょうか?
上述のとおり、2進数の場合はひとつの位に0か1の2つの数字しか入りません。そして、2になったタイミングで次の位に上がります。この時、各位に注目すると、一の位は2の0乗(2^0=1)、十の位は2の1乗(2^1=2)、百の位は2の2乗(2^2=4)というように「2の累乗の指数が 1 ずつ増えていくたびに位がひとつ上がる」という法則性が分かります。つまり、法則性は10進数と同じなのです。
ただ、底の値が異なるため直感的には分かりにくいかもしれません。
以下の表は、10進数とバイナリ(2進数)を比較したものになります。
10進数 | 2進数 | 10進数 | 2進数 | 10進数 | 2進数 | 10進数 | 2進数 |
---|---|---|---|---|---|---|---|
0 | 0 | 16 | 10000 | 32 | 100000 | 48 | 110000 |
1 | 1 | 17 | 10001 | 33 | 100001 | 49 | 110001 |
2 | 10 | 18 | 10010 | 34 | 100010 | 50 | 110010 |
3 | 11 | 19 | 10011 | 35 | 100011 | 51 | 110011 |
4 | 100 | 20 | 10100 | 36 | 100100 | 52 | 110100 |
5 | 101 | 21 | 10101 | 37 | 100101 | 53 | 110101 |
6 | 110 | 22 | 10110 | 38 | 100110 | 54 | 110110 |
7 | 111 | 23 | 10111 | 39 | 100111 | 55 | 110111 |
8 | 1000 | 24 | 11000 | 40 | 101000 | 56 | 111000 |
9 | 1001 | 25 | 11001 | 41 | 101001 | 57 | 111001 |
10 | 1010 | 26 | 11010 | 42 | 101010 | 58 | 111010 |
11 | 1011 | 27 | 11011 | 43 | 101011 | 59 | 111011 |
12 | 1100 | 28 | 11100 | 44 | 101100 | 60 | 111100 |
13 | 1101 | 29 | 11101 | 45 | 101101 | 61 | 111101 |
14 | 1110 | 30 | 11110 | 46 | 101110 | 62 | 111110 |
15 | 1111 | 31 | 11111 | 47 | 101111 | 63 | 111111 |
ビットとバイトとは
コンピュータの世界において、0 と 1 はデータの最小単位であり、これらひとつひとつを **1ビット(1bit)**と言います。そして、8bitのことを **1バイト(1byte)**と言います。スマートフォンのストレージや通信環境など、一般的によく目にするのはバイトの方かもしれません。
それでは、上の対応表を改めて確認してみましょう。10進数の4は2進数で100なので3bit、8は1000なので4bitということになります。
ビットやバイトという単位は、今後学習していく過程で何度も出てくると思います。
その度に「データの大きさを表す単位なんだ~」ということを思い出していただければと思います。
エンコードとデコード
エンコードとは、何らかのルール(データの変換方式)に従って、データの形式を変換することです。デコードはその逆で、もとの形式に戻すことです。
Base64によるエンコード/デコードの方法
Base64では、以下に示す、英数字と記号を合わせた全64種類を用いてエンコードします。
- アルファベット(52種):小文字「a~z」, 大文字「A~Z」
- 数字(10種):「0~9」
- 記号(2種):「+」,「/」
10進数、2進数、文字(英数字+記号)の対応は以下の表のようになります。
10進数 | 2進数 | 文字 | 10進数 | 2進数 | 文字 | 10進数 | 2進数 | 文字 | 10進数 | 2進数 | 文字 |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | 000000 | A | 16 | 010000 | Q | 32 | 100000 | g | 48 | 110000 | w |
1 | 000001 | B | 17 | 010001 | R | 33 | 100001 | h | 49 | 110001 | x |
2 | 000010 | C | 18 | 010010 | S | 34 | 100010 | i | 50 | 110010 | y |
3 | 000011 | D | 19 | 010011 | T | 35 | 100011 | j | 51 | 110011 | z |
4 | 000100 | E | 20 | 010100 | U | 36 | 100100 | k | 52 | 110100 | 0 |
5 | 000101 | F | 21 | 010101 | V | 37 | 100101 | l | 53 | 110101 | 1 |
6 | 000110 | G | 22 | 010110 | W | 38 | 100110 | m | 54 | 110110 | 2 |
7 | 000111 | H | 23 | 010111 | X | 39 | 100111 | n | 55 | 110111 | 3 |
8 | 001000 | I | 24 | 011000 | Y | 40 | 101000 | o | 56 | 111000 | 4 |
9 | 001001 | J | 25 | 011001 | Z | 41 | 101001 | p | 57 | 111001 | 5 |
10 | 001010 | K | 26 | 011010 | a | 42 | 101010 | q | 58 | 111010 | 6 |
11 | 001011 | L | 27 | 011011 | b | 43 | 101011 | r | 59 | 111011 | 7 |
12 | 001100 | M | 28 | 011100 | c | 44 | 101100 | s | 60 | 111100 | 8 |
13 | 001101 | N | 29 | 011101 | d | 45 | 101101 | t | 61 | 111101 | 9 |
14 | 001110 | O | 30 | 011110 | e | 46 | 101110 | u | 62 | 111110 | + |
15 | 001111 | P | 31 | 011111 | f | 47 | 101111 | v | 63 | 111111 | / |
※上記に加えて、パディング(字余り)を埋合わせるために「=」も使用します。
※上記のように、多くの場合2進数は6bitで表記します。6bitで表記する場合は、足りない部分を0で補います。
Base64によるエンコードの手順
Base64では、以下の手順でエンコードしていきます。例とともに確認していきましょう。
-
もとのデータ(文字列)をバイナリに変換します。このとき、文字列はASCIIコードの変換表にもとづいて変換されます。
# こちらの例では、もとの文字列は Base64 とします。 # 標準入力から受け取った文字列"Base64"を xxdコマンドを使用してバイナリに変換しましょう。 $ echo -n Base64 | xxd -b 00000000: 01000010 01100001 01110011 01100101 00110110 00110100 Base64
-
そのバイナリを先頭から6bitずつに分割します。この時、6bitに満たない部分は0で埋め合わせます。今回はピッタリなのでそのままでOKです。
(例) {010000, 100110, 000101, 110011, 011001, 010011, 011000, 110100}
-
『Base64によるエンコード&デコードの方法』の表に従って、バイナリを文字に変換します。さらに4文字ずつに分割します。
(例) {QmFz, ZTY0}
-
4文字に満たない部分は、「=」で埋め合わせます。今回はピッタリなのでそのままでOKです。
-
最後に、全ての文字を繋げてひとつの文字列にしたら完成です。
(例) {QmFzZTY0}
※ ASCIIコードとは、英語の文字列をコンピュータが識別できるようにバイナリに変換する際の文字コードのひとつです。文字コードとは、各文字に割り当てられた数字のことです。ASCIIコードは、ASA(American Standards Association, 現在のANSI)によって標準化され、世界的に広く使われています。ASCIIコードはバイナリだと8bitです。
※ xxd
コマンドは、文字列を16進数や2進数に変換するためのコマンドです。今回のようにバイナリに変換する場合には、-b
オプションを使用します。
base64コマンド
Linuxには、Base64によるエンコード/デコードが簡単に行えるbase64
コマンドがあります。
以下の例とともに使い方を確認していきましょう。
基本的な使い方
base64
コマンドは以下のように文字列やファイルなどを指定して使用します。
文字列をエンコード/デコードする場合
# 文字列Base64をエンコードします。
echo -n "Base64" | base64
QmFzZTY0
--------------------------------------------
# デコードする場合には、-dオプションを使います。
echo -n "QmFzZTY0" | base64 -d
Base64
ファイルをエンコード/デコードする場合
# sample.dataというファイルにメッセージを記述します。
vi sample.data
=========================
1| Hello world!
2| I am a Kryptonian!
=========================
# ファイルをエンコードするときは、base64コマンドの後ろにファイル名を記述します。
base64 sample.data
SGVsbG8gd29ybGQhCkkgYW0gYSBLcnlwdG9uaWFuIQo=
----------------------------------------------------------------------------
# sample.dataをエンコードしたものをencoded.txtに出力します。
base64 sample.data > encoded.txt
# encoded.txtをデコードします。
base64 -d encoded.txt
Hello world!
I am a Kryptonian!
このように、base64
コマンドを使うことで簡単にエンコード/デコードができます。
まとめ
今回は、Base64とデータについて学んできました。
よく利用されるエンコード方式ですので、しっかりとその仕組みや役割などを理解しましょう。
さらに、Envader セキュリティコースの『簡易的な暗号について』では、base64が登場します。
そちらの問題も非常に勉強になるので、是非チャレンジしてみてください!
問題を解くためには、十分な画面サイズのPC環境をご利用下さい。