データ符号化 Base64 Base85 まとめ
先日開催された Codegate CTF で出題された問題
Decode it :
9P&;gFD,5.BOPCdBl7Q+@V'1dDK?qL
こちらは Base85 でデコードすると flag をゲットできます
今回は主要な BaseXX をまとめます(BaseXX という呼称はこの記事で便宜的に使用されるもので一般的なものではありません)
データ符号化について
バイナリやマルチバイト文字とアスキー文字をエンコード・デコードするための仕様です
BaseXX の XX の部分は使用されるアスキー文字の数を表したものです
この数が大きいほど,データを短く表現できるため効率が良くなります
主要な BaseXX
Base16,Base32,Base64 は RFC 4648 で定義されています
(RFC 4648 は RFC 3548 を改訂したものです)
Base64 には URL で特別な処理に使用される +
と /
が含まれているため,URL 用に -
と _
で置き換えた base64url が定義されています
Base85(ASCII85) は RFC では定義されておらず,一般に認められているという状態です
ASCII85 はエスケープ文字を含むことがデメリットであるため,ダブルクォート・シングルクォート・バックスラッシュなどが除かれた RFC 1924 準拠 IPv6 バージョンや Z85 という派生型が使用されることがあります
使用される文字
Base16
0123456789ABCDEF
Base32
ABCDEFGHIJKLMNOPQRSTUVWXYZ234567
base64
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
base64url
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_
ASCII85
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstu
Base85 IPv6
0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!#$%&()*+-;<=>?@^_`{|}~
Z85
0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-:+=^!/*?&<>()[]{}@%$#
Base32 と base64 ではパディングのために上記の表の他に =
が使われます
変換してみる
こちらのオンラインツールが使いやすいです
https://gchq.github.io/CyberChef/
original : Hello World!
Base16 : 48656C6C6F20576F726C6421
Base32 : JBSWY3DPEBLW64TMMQQQ====
Base64 : SGVsbG8gV29ybGQh
Base64url : SGVsbG8gV29ybGQh
ASCII85 : 87cURD]i,"Ebo80
Base85 IPv6 : NM&qnZy;B1a%^NF
Z85 : nm=QNzY&b1A+]nf
Python でエンコード&デコードする
Python にはbase64パッケージがあり、Base16, Base32, Base64, Base85 のエンコードとデコードを行うことができます
import base64
text = "Hello World!"
text_base16 = base64.b16encode(text.encode())
print(text_base16)
# b'48656C6C6F20576F726C6421'
text_base32 = base64.b32encode(text.encode())
print(text_base32)
# b'JBSWY3DPEBLW64TMMQQQ===='
text_base64 = base64.b64encode(text.encode())
print(text_base64)
# b'SGVsbG8gV29ybGQh'
text_urlsafe_base64 = base64.urlsafe_b64encode(text.encode())
print(text_urlsafe_base64)
# b'SGVsbG8gV29ybGQh'
text_ascii85 = base64.a85encode(text.encode())
print(text_ascii85)
# b'87cURD]i,"Ebo80'
text_base85 = base64.b85encode(text.encode())
print(text_base85)
# b'NM&qnZy;B1a%^NF'
text_base16 = "48656C6C6F20576F726C6421"
print(base64.b16decode(text_base16))
text_base32 = "JBSWY3DPEBLW64TMMQQQ===="
print(base64.b32decode(text_base32))
text_base64 = "SGVsbG8gV29ybGQh"
print(base64.b64decode(text_base64))
text_urlsafe_base64 = "SGVsbG8gV29ybGQh"
print(base64.urlsafe_b64decode(text_urlsafe_base64))
text_ascii85 = '87cURD]i,"Ebo80'
print(base64.a85decode(text_ascii85))
text_base85 = "NM&qnZy;B1a%^NF"
print(base64.b85decode(text_base85))
# b'Hello World!'