先日開催された Codegate CTF で出題された問題

Decode it :
9P&;gFD,5.BOPCdBl7Q+@V'1dDK?qL

こちらは Base85 でデコードすると flag をゲットできます

今回は主要な BaseXX をまとめます(BaseXX という呼称はこの記事で便宜的に使用されるもので一般的なものではありません)

データ符号化について

バイナリやマルチバイト文字とアスキー文字をエンコード・デコードするための仕様です

BaseXX の XX の部分は使用されるアスキー文字の数を表したものです

この数が大きいほど,データを短く表現できるため効率が良くなります

主要な BaseXX

Base16Base32Base64RFC 4648 で定義されています

RFC 4648RFC 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!'