Base32 をデコードする方法
- 入力 · Base32(RFC 4648)に文字列を貼り付けます。大文字でも小文字でもよく、グループ間の空白や改行も受け付け、
=のパディングは任意です。 - デコードしたテキストを出力 · テキストで読みます。デフォルトの文字コードは UTF-8 です。テキストが別のシステムから来た場合は、出力の下の文字コードを変更してください。
- 出力が記号の羅列になる場合、データはバイナリです。変換先を Hex(16進数)か Base64 にしてバイト列を確認するか、バイトを保存でファイルとしてダウンロードします。
- 入力が別のアルファベットを使っている場合は、変換元を Base32hex、Crockford Base32、z-base-32 に変更します。
- エンコードするには、方向の切り替えでテキスト → Base32(RFC 4648)をクリックするか、Base32 エンコーダーを使います。
デコーダーが受け付けるもの・拒否するもの
このデコーダーは、書式には寛容で、内容には厳格です。
| 入力 | 結果 |
|---|---|
JBSWY3DP | Hello |
jbswy3dp | Hello。大文字小文字は問わない |
JBSW Y3DP EHPK 3PXP | 10 バイト、16進数で 48656c6c6f21deadbeef |
MZXW6YQ | foob。パディングの欠落は問題なし |
JBSWY3D0 | エラー:位置 8 に予期しない文字 "0" があります |
エラーは、アルファベットに含まれない最初の文字を指します。0、1、8、9 はほぼ確実に別の Base32 アルファベットを使っている印で、+ や / なら実は Base64 です。Base64 デコーダーを試してください。
2 段階認証(TOTP)のシークレットをデコードする
認証アプリの設定中に表示される鍵は、jbsw y3dp ehpk 3pxp のようにグループ分けされていることが多く、RFC 4648 の Base32 です。デコードすると生の HMAC 鍵が得られます。ランダムなバイト列なので、テキストではなく Hex(16進数)で確認してください。長さから鍵のサイズがわかります。16 文字なら 10 バイト、32 文字なら 20 バイト(RFC 4226 が推奨する 160 ビット)、52 文字なら 32 バイトです。
正しいシークレットかどうかを確かめるには、そこからコードを生成してみます。次の Python 関数は同じく寛容な方法でシークレットをデコードし、RFC 6238 に従ってコードを計算します。
import base64, hashlib, hmac, struct
def totp(secret, t, digits=6, step=30):
s = secret.replace(" ", "").upper()
key = base64.b32decode(s + "=" * (-len(s) % 8))
mac = hmac.new(key, struct.pack(">Q", t // step), hashlib.sha1).digest()
off = mac[-1] & 0x0F
code = struct.unpack(">I", mac[off:off + 4])[0] & 0x7FFFFFFF
return str(code % 10**digits).zfill(digits)
totp("GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ", 59, 8) # '94287082'
このシークレットと期待される 94287082 は、RFC 6238 の SHA-1 のテストベクターです。現在のコードを得るには、t に int(time.time()) を渡します。その他のデコードのパターンは Python のページにあります。
IPFS CIDv1 など接頭辞付きの Base32
Base32 の前に目印を付ける形式もあります。IPFS CIDv1 の文字列は b で始まります。これはパディングなしの小文字 RFC 4648 Base32 を表す multibase のコードで、bafybei… の b が接頭辞、afybei… がデータです。b を取り除いてデコードし、変換先を Hex(16進数)にします。最初のバイトは CID のバージョン(01)、コンテンツの種類(dag-pb なら 70)、マルチハッシュのヘッダー(32 バイトの SHA-256 なら 1220)です。
Tor v3 の onion アドレスも、接頭辞はありませんが同じ仕組みです。.onion の前の 56 文字は 35 バイトの Base32 で、32 バイトの公開鍵、2 バイトのチェックサム、バージョンバイト(03)からなります。
よくある問題
- Python が
binascii.Error: Non-base32 digit foundを出す。 入力が小文字です。b32decodeにcasefold=Trueを渡すか、先に.upper()を呼んでください。 - Python が
binascii.Error: Incorrect paddingを出す。=が取り除かれています。上の関数のように、長さが 8 の倍数になるまでパディングしてください。 base32 -dがinvalid inputと言う。 GNU coreutils は小文字も空白も受け付けません。先に文字列を整えるか、ここでデコードしてください。- テキストにデコードはできるが、内容が違う。 Base32hex や Crockford の文字列は、間違ったアルファベットでもエラーなしにデコードされてしまいます。出どころが「Base32」と言っていて、文字列に
0、1、8、9が含まれないなら、RFC 4648 が最も可能性の高い候補です。そうでなければ他の 2 つを試してください。
よくある質問
TOTP のシークレットをデコードするにはどうすればいいですか?
シークレット(otpauth:// リンクの secret= の値、または QR コードの代わりにアプリが表示するテキストの鍵)を貼り付け、変換先を Hex(16進数)にします。結果が生の HMAC 鍵です。ランダムなバイト列なので、テキストの出力は文字化けしたように見えますが、それで正常です。
Base32 をデコードすると Python が Incorrect padding と言うのはなぜですか?
base64.b32decode は長さが 8 の倍数であることを求めます。先に欠けた = を足してください:s + "=" * (-len(s) % 8)。このデコーダーにはパディングは不要です。
ここで ULID をデコードできますか?
直接はできません。ULID は Crockford のアルファベットを使いますが、1 つの 128 ビットの数を 26 文字で表し、先頭に 2 ビットの余りがあります。ここの Crockford オプションは最初の文字からバイトをビット単位で詰めるので、ULID ではずれたバイト列が返ります。
Base32 で無効な文字はどれですか?
RFC 4648 の Base32 では、A–Z、2–7、末尾の = 以外のすべてです。数字の 0、1、8、9 があれば、たいていは base32hex か Crockford の文字列です。変換元を切り替えて試してください。