言語:日本語

tools / aes

aes/

AES の共通鍵暗号化と復号。モード、パディング、鍵と IV の形式、文字コードを選べ、結果は Java・CryptoJS と一致します。鍵はブラウザの外に出ません。

平文

暗号文

履歴

暗号化・復号に成功するたびに自動で記録し、最新 20 件をこの端末のブラウザだけに保存します。鍵は保存しませんが、IV と復号した平文は保存されるので、共用パソコンでは使い終わったら履歴を消去してください。

AES・DES・RSA とは? その違い

AES と DES は共通鍵暗号です。暗号化と復号に同じ鍵を使い、1 本の鍵でドアを閉めて開けるようなものです。高速で大量のデータに向いていますが、その鍵をどうやって安全に相手へ渡すかが課題になります。

DES は 1970 年代の古い標準で、実質的な鍵長は 56 ビットしかなく、今では専用ハードウェアやコンピューター群で総当たり解読できます。まだ DES を使う古いシステムとの連携専用です。AES は DES に代わる標準で、鍵は 128・192・256 ビット。現在、現実的な解読方法はなく、データ暗号化の第一候補です。

RSA は公開鍵暗号です。鍵はペアになっていて、公開鍵は誰に渡してもよく暗号化に使い、秘密鍵は自分だけが持って復号に使います。誰でも手紙を入れられて、自分だけが鍵で開けられる郵便受けのようなものです。事前に鍵を取り決める必要はありませんが、遅く、一度に数百バイトしか暗号化できません。実際のシステムでは両方を組み合わせ、ランダムに作った AES 鍵を RSA で暗号化して相手に送り、本体のデータは AES で暗号化するのが一般的です。

暗号モードとは? どれを選ぶか

AES は一度に 16 バイトしか暗号化できず、モードは長いデータをどうブロックに分け、ブロック同士をどうつなぐかを決めます。ECB は各ブロックを個別に暗号化するため、同じ内容は同じ暗号文になりデータの規則性が漏れるので非推奨です。CBC は各ブロックを直前の暗号文と混ぜてから暗号化し、最初のブロックは IV と混ぜます。最も一般的な選択です。CFB・OFB・CTR は AES を鍵ストリームに変えてデータと 1 バイトずつ XOR するので、パディングが不要です。GCM は CTR に認証タグ(Tag)を加えたもので、暗号文が改ざんされると復号に失敗します。現在最も推奨されるモードです。

IV とパディングの役割

IV(初期化ベクトル)は、同じ内容でも毎回違う暗号文にするためのものです。秘密にする必要はなく暗号文と一緒に送れますが、同じ鍵で使い回してはいけません。GCM では特に重要です。ECB 以外のモードは IV が必要で、GCM は 12 バイト推奨、その他は 16 バイト固定です。

ECB と CBC はデータ長が 16 バイトの倍数である必要があり、足りない分はパディング方式に従って埋めます。AES では PKCS5Padding と PKCS7Padding はまったく同じで、最もよく使われます。ZeroPadding は 0 で埋め、復号時に末尾の 0 バイトをすべて取り除くため、平文自体が 0 バイトで終わる場合は一緒に消えます。NoPadding は何も足さないので、長さを自分で合わせる必要があります。GCM はパディングを使いません。

Java・CryptoJS の書き方との対応

Java の Cipher.getInstance("AES/CBC/PKCS5Padding") は CBC と PKCS5Padding を選ぶのと同じで、"AES" だけなら既定は ECB と PKCS5Padding です。Java の CTR と GCM は NoPadding のみ、GCM の Tag は 96〜128 ビットのみ対応です。CryptoJS の CryptoJS.pad.Pkcs7 は PKCS7Padding に当たり、ZeroPadding・AnsiX923・Iso10126・Iso97971 は同名で対応します。CryptoJS.AES.encrypt に文字列のパスフレーズを直接渡すと、鍵を自動生成して U2FsdGVkX1 で始まる結果を出力しますが、この使い方には対応していません。16・24・32 バイトの鍵と IV を渡してください。

GCM の Tag と AAD とは

Tag は GCM が計算する検証値で、暗号化結果の末尾の数バイトが Tag です(128 ビットなら 16 バイト)。AAD は追加認証データで、たとえばメッセージヘッダーです。AAD 自体は暗号化されませんが検証の対象になるため、復号時に同じ内容を入れないと検証に失敗します。

よくある質問

「鍵が N バイトです」「IV が N バイトです」と表示されたらどうすればいいですか?

まず形式が合っているか確認してください。同じ 32 文字でも、string 形式なら 32 バイト、hex 形式なら 16 バイトです。AES の鍵は 16・24・32 バイトのいずれかで、ECB と GCM 以外の IV はちょうど 16 バイトが必要です。自動で 0 埋めや切り詰めはせず、現在のバイト数は鍵と IV の見出しの横に表示されます。string 形式では選択した文字コードでバイト数が決まり、日本語や中国語の文字 1 文字は UTF-8 で 3 バイトです。バックエンド側でパスフレーズに 0 埋めやハッシュなどの処理をしている場合は、先に最終的なバイト列を求めて、hex か base64 で入力してください。

復号で「パディングが不正」と表示されたらどうすればいいですか?

復号した最後のブロックが、選んだパディング規則に合っていないという意味です。たいていは鍵・IV・モード・パディングのどれかが暗号化時と違うか、暗号文のコピーが不完全です。暗号化した側のパラメータと 1 つずつ照らし合わせてください。鍵の形式や暗号文の形式(hex と base64)を間違えた場合も同じエラーになります。ZeroPadding と NoPadding はパディングを検査しないのでこのエラーは出ませんが、パラメータが違うと結果は文字化けになります。

復号結果の先頭だけ文字化けする、または「正しい UTF-8 テキストではありません」と表示される

まず IV を確認してください。暗号文が 1 ブロックより長い場合、CBC と CFB モードで IV が違うと、壊れるのは最初の 16 バイトのブロックだけで、後ろの内容は正常に復号され、パディングのエラーも出ないため、先頭だけが文字化けして後ろは正しい、という状態になります。結果が正しいテキストではないと表示される場合は、文字コードが暗号化側と違う可能性もあります。たとえば相手が GBK を使っている場合です。出力形式を hex にすると、まず復号されたバイト列そのものが正しいか確認できます。

GCM の復号で「Tag の検証に通りません」と表示されたらどうしますか?

鍵・IV・AAD・Tag 長のどれかが暗号化時と違うか、暗号文が改ざんされているという意味です。入力の末尾部分が Tag として扱われ、その長さは「Tag 長」の設定(デフォルトは 128 ビット、つまり 16 バイト)で決まるため、暗号文と Tag は続けて入力する必要があります。相手が Tag を別に渡してきた場合は、先に暗号文の後ろにつなげてください。AAD の形式はデフォルトが hex なので、文字列で入力するときは形式を変えてください。暗号化時に AAD を使っていなければ、復号時も空欄にします。

Java や Python などのバックエンドと結果が一致しません。どう調べればいいですか?

次の順に確認してください。モードとパディング、鍵と IV の形式およびバイト数、文字コード、入出力の形式です。string 形式の平文は前後の空白が取り除かれないため、末尾に改行が 1 つあるだけで別のデータになります。CTR・CFB・OFB でも、ここでは選んだパディングで埋められるので、PKCS5Padding を選ぶと暗号文が平文より長くなります。バックエンドが NoPadding なら、ここでも NoPadding を選んでください。ここでの CFB は 128 ビットのブロック単位のもので、相手が CFB8 を使っていると一致しません。

暗号文は hex と base64 のどちらにすべきですか?間違えるとどうなりますか?

相手の出力に合わせてください。0-9 と a-f だけならば hex、大文字小文字の英字や +、/、末尾の = があれば base64 です。復号で形式を間違えても、すぐにエラーになるとは限りません。hex で使われる文字はすべて base64 の有効な文字でもあるため、誤ったバイト列に変換されるだけで、あとから「16 の倍数ではありません」やパディングのエラーとして表れます。base64 の - と _(URL セーフ形式)や = の省略は認識され、hex の空白・コロン・0x プレフィックスは無視されます。

履歴には何が保存されますか?アップロードされますか?

この端末のブラウザの localStorage にだけ保存され、アップロードはされません。ページのコードにも通信処理はありません。暗号化または復号に成功するたびに 1 件記録され、最大 20 件まで保持されます。入力か結果が 2 万文字を超えるものは記録されません。記録にはパラメータ・IV・AAD・入力・結果と、鍵から計算した 8 文字のフィンガープリント(各記録の # の後ろの文字列で、同じ鍵かどうかの判別に使います)が含まれますが、鍵そのものは保存されないため、「読み込む」を押したあとは鍵を入力し直す必要があります。1 件ずつ削除でき、共用パソコンでは使い終わったら「履歴を消去」を押してください。

ランダムな鍵や IV を自動生成できますか?

できません。生成ボタンはないので、鍵と IV は自分で入力します。同じ平文・鍵・IV・パラメータなら暗号化の結果は毎回同じで、結果が変わるのは ISO10126 パディングがランダムなバイトを混ぜる場合だけです。ランダムな値が必要なときは自分で生成してください。たとえばコマンドラインで openssl rand -hex 16 を実行すると 16 バイト分が出力されるので、形式を hex にして入力します。