AES のテキストを復号する方法
- 復号が選択され、サンプルが読み込まれた状態になっています。パスワードは
correct horse battery stapleなので、まず成功する様子を確認できます。 - 暗号化された Base64 に文字列を貼り付けます。標準の Base64 でも URLセーフな Base64 でもよく、
=の有無も問いません。改行は無視されます。 - 鍵の種類がパスワードなら、パスワードを入力します。送り手が変更していれば、同じ PBKDF2 反復回数(デフォルト 310,000)も入力します。生の鍵なら、16、24、32 バイトの鍵を Base64 か 16進数で貼り付けます。
- 復号を押すか、パスワード欄で Enter を押します。メッセージは復号されたテキストに表示されます。内容が UTF-8 テキストでない場合は Base64 で表示され、ダウンロードで元のバイト列を保存できます。
成功すると「復号・認証に成功しました」と表示されます。GCM タグが一致したので、テキストは送り手が暗号化したものとまったく同じです。
Base64 の復号か、Base64 のデコードか
手元にあるのがただの Base64 文字列なのに、「Base64 復号」で検索する人は少なくありません。Base64 は鍵のないエンコーディングなので、そうした文字列はデコードするだけでよく、それは Base64 デコーダーの仕事です。簡単な見分け方があります。デコードして読めるテキストや見覚えのあるファイルになるなら、そもそも暗号化されていません。ランダムに見えるバイト列になり、誰かからパスワードを渡されているなら、それは暗号文で、下の形式で作られたものであれば、このページで復号できます。違いは Base64 は暗号化ではないで説明しています。
既知の値で試す
次の文字列は、形式のドキュメントにある Python の encrypt() 関数を使い、パスワード correct horse battery staple でブラウザの外で暗号化したものです。
SD8wB+5V2GRfupy/yEY1xTUE8d5z9fwbzQ0gxeRzbtym1I4O7A9Q2NYnbYxEPYgvwJ4Q7DU5q/sugOx+B1Ro3ujkDXvnl/y2XYuji9A=
復号すると Meet me at the usual place at 10. になります。104 文字をデコードすると 77 バイトで、内訳はソルト 16、IV 12、暗号文 33、タグ 16 です。結果の下の内訳表示には、貼り付けたどの文字列についても同じ分割が表示されます。
エラーメッセージとその意味
| メッセージ | よくある原因 |
|---|---|
| 復号に失敗しました。パスワードや鍵、モードが違うか、データが改ざんされています | パスワードの誤り、反復回数の違い、パスワード用の暗号文に生の鍵を使った(またはその逆)、コピー時の文字の欠落 |
| このツールの暗号文としては短すぎます | 文字列が途中で切れているか、そもそもこのツールのものではない |
| AES 鍵は 16、24、32 バイトのいずれかである必要があります | 生の鍵の長さが違う。Base64 か 16進数かを確認する |
| このブラウザは 192 ビットの AES 鍵に対応していません | Chrome と Edge は 128 ビットと 256 ビットの鍵しか使えない。Python か Node.js で復号する |
| 反復回数は 1,000 ~ 10,000,000 の範囲で指定してください | 反復回数の欄にありえない値が入っている |
GCM は、パスワードの誤りとデータの改ざんを区別しません。どちらの場合もタグが一致せず、何も出力されません。CBC のような認証のないモードでは、エラーの代わりに意味のないデータが返ってくることがあります。
このツールで開けない文字列
ここでの形式は固定です。パスワードなら Base64( salt[16] ‖ iv[12] ‖ ciphertext ‖ tag[16] )、生の鍵なら Base64( iv[12] ‖ ciphertext ‖ tag[16] ) で、AES-GCM と、310,000 回の PBKDF2-HMAC-SHA256 を使います。他のツールは別の形式で書き出し、多くの場合は先頭の文字で見分けがつきます。
| 先頭 | 作成元 | 復号方法 |
|---|---|---|
U2FsdGVkX1 | パスフレーズを使った openssl enc または CryptoJS(Salted__ ヘッダー) | 元の暗号方式と KDF のオプションを付けた openssl enc -d -a |
gAAAAA | Fernet トークン(Python の cryptography) | Fernet(key).decrypt(token) |
-----BEGIN PGP MESSAGE----- | OpenPGP | gpg --decrypt |
-----BEGIN AGE ENCRYPTED FILE----- | age | age --decrypt |
見分けのつく先頭文字はよくある Base64 の接頭辞にもまとめています。
Node.js と Python での復号
同じ形式はブラウザがなくても扱えます。Node.js では次のとおりです。
const crypto = require("crypto");
function decrypt(b64, password) {
const data = Buffer.from(b64, "base64");
const salt = data.subarray(0, 16), iv = data.subarray(16, 28);
const tag = data.subarray(data.length - 16), ct = data.subarray(28, data.length - 16);
const key = crypto.pbkdf2Sync(password, salt, 310000, 32, "sha256");
const d = crypto.createDecipheriv("aes-256-gcm", key, iv);
d.setAuthTag(tag);
return Buffer.concat([d.update(ct), d.final()]).toString("utf8");
}
function encrypt(text, password) {
const salt = crypto.randomBytes(16), iv = crypto.randomBytes(12);
const key = crypto.pbkdf2Sync(password, salt, 310000, 32, "sha256");
const c = crypto.createCipheriv("aes-256-gcm", key, iv);
const ct = Buffer.concat([c.update(text, "utf8"), c.final()]);
return Buffer.concat([salt, iv, ct, c.getAuthTag()]).toString("base64");
}
Python で生の鍵の文字列を扱う場合は、ソルトと PBKDF2 を省き、IV をバイト 0 から始めます。
import base64
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
def decrypt_raw(b64, key_b64):
data = base64.b64decode(b64)
iv, ct = data[:12], data[12:]
return AESGCM(base64.b64decode(key_b64)).decrypt(iv, ct, None).decode("utf-8")
Python のパスワード版は AES 暗号化のページにあります。この種の暗号化は、ある人から別の人へ秘密を渡すためのものです。届いたら暗号文を残しておかず、パスワードマネージャーやシークレットマネージャーに移してください。
よくある質問
パスワードなしで Base64 を復号できますか?
ただの Base64 ならできます。復号するものが何もないからです。Base64 デコーダーに貼り付けてください。Base64 になった AES の暗号文なら、できません。パスワードや鍵がなければバイト列は復元できず、強力なパスワードを推測できるツールもありません。
パスワードは正しいのに「パスワードが違う」と表示されるのはなぜですか?
まず PBKDF2 の反復回数を確認してください。反復回数は暗号文に保存されないので、送り手が変更した場合はその値を教えてもらう必要があります。また、文字列が完全にコピーされているか、本当にこのツールの形式のものかも確かめてください。
OpenSSL や CryptoJS で暗号化したテキストを復号できますか?
できません。U2FsdGVkX1 で始まる文字列は OpenSSL の Salted__ ヘッダーを持ち、別の鍵導出と、たいていは CBC モードを使っています。暗号化したときと同じオプションで openssl enc -d を使って復号してください。
復号したテキストはどうなりますか?
ページに表示されるだけで、他のどこにも送られません。復号は WebCrypto を使ってブラウザ内で行われ、ページの Content Security Policy が Cloudflare のページビュー計測以外のネットワーク通信をすべてブロックするため、パスワードもメッセージも送信されません。