1. ホーム
  2. コース一覧
  3. セキュリティ基礎コース
  4. Base64について

セキュリティ基礎コース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進数
0016100003210000048110000
1117100013310000149110001
21018100103410001050110010
31119100113510001151110011
410020101003610010052110100
510121101013710010153110101
611022101103810011054110110
711123101113910011155110111
8100024110004010100056111000
9100125110014110100157111001
10101026110104210101058111010
11101127110114310101159111011
12110028111004410110060111100
13110129111014510110161111101
14111030111104610111062111110
15111131111114710111163111111

ビットとバイトとは

コンピュータの世界において、0 と 1 はデータの最小単位であり、これらひとつひとつを **1ビット(1bit)**と言います。そして、8bitのことを **1バイト(1byte)**と言います。スマートフォンのストレージや通信環境など、一般的によく目にするのはバイトの方かもしれません。

それでは、上の対応表を改めて確認してみましょう。10進数の4は2進数で100なので3bit、8は1000なので4bitということになります。

ビットやバイトという単位は、今後学習していく過程で何度も出てくると思います。

その度に「データの大きさを表す単位なんだ~」ということを思い出していただければと思います。

エンコードとデコード

エンコードとは、何らかのルール(データの変換方式)に従って、データの形式を変換することです。デコードはその逆で、もとの形式に戻すことです。

Base64によるエンコード/デコードの方法

Base64では、以下に示す、英数字と記号を合わせた全64種類を用いてエンコードします。

  • アルファベット(52種):小文字「az」, 大文字「AZ
  • 数字(10種):「09
  • 記号(2種):「+」,「/

10進数、2進数、文字(英数字+記号)の対応は以下の表のようになります。

10進数2進数文字10進数2進数文字10進数2進数文字10進数2進数文字
0000000A16010000Q32100000g48110000w
1000001B17010001R33100001h49110001x
2000010C18010010S34100010i50110010y
3000011D19010011T35100011j51110011z
4000100E20010100U36100100k521101000
5000101F21010101V37100101l531101011
6000110G22010110W38100110m541101102
7000111H23010111X39100111n551101113
8001000I24011000Y40101000o561110004
9001001J25011001Z41101001p571110015
10001010K26011010a42101010q581110106
11001011L27011011b43101011r591110117
12001100M28011100c44101100s601111008
13001101N29011101d45101101t611111019
14001110O30011110e46101110u62111110+
15001111P31011111f47101111v63111111/

※上記に加えて、パディング(字余り)を埋合わせるために「=」も使用します。

※上記のように、多くの場合2進数は6bitで表記します。6bitで表記する場合は、足りない部分を0で補います。

Base64によるエンコードの手順

Base64では、以下の手順でエンコードしていきます。例とともに確認していきましょう。

  1. もとのデータ(文字列)をバイナリに変換します。このとき、文字列はASCIIコードの変換表にもとづいて変換されます。

    # こちらの例では、もとの文字列は Base64 とします。
    # 標準入力から受け取った文字列"Base64"を xxdコマンドを使用してバイナリに変換しましょう。
    $ echo -n Base64 | xxd -b
    00000000: 01000010 01100001 01110011 01100101 00110110 00110100  Base64
  2. そのバイナリを先頭から6bitずつに分割します。この時、6bitに満たない部分は0で埋め合わせます。今回はピッタリなのでそのままでOKです。

    (例) {010000, 100110, 000101, 110011, 011001, 010011, 011000, 110100}

  3. 『Base64によるエンコード&デコードの方法』の表に従って、バイナリを文字に変換します。さらに4文字ずつに分割します。

    (例) {QmFz, ZTY0}

  4. 4文字に満たない部分は、「=」で埋め合わせます。今回はピッタリなのでそのままでOKです。

  5. 最後に、全ての文字を繋げてひとつの文字列にしたら完成です。

    (例) {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環境をご利用下さい。