テキストをパスワードで暗号化する方法
- 暗号化と鍵の種類のパスワードを選択したままにします。
- パスワードを入力します。パスワードを表示をオンにすると、入力中のパスワードが見えます。PBKDF2 反復回数は、特に理由がなければ 310,000 のままにしてください。復号する人も同じ値を入力する必要があります。
- 平文にメッセージを入力し、暗号化を押します。パスワード欄で Enter、またはテキスト欄で Ctrl+Enter でも実行できます。
- 暗号化された Base64 をコピーするか、ダウンロードします。文字列を URL に入れる場合は URLセーフで出力(- _、= なし) にチェックを入れます。
出力の下には、ソルト、IV、暗号文、タグのサイズと合計、使った鍵導出の内訳が表示されます。結果を送るときは、Base64 を 1 つのメッセージで送り、パスワードは電話や別のチャットアプリなど別の経路で伝えてください。受け取った人は AES 復号を開き、逆の手順をたどります。
このツールの用途
このツールは、もっとよい経路がないときに、短いテキストを安全に共有するためのものです。来客用の Wi-Fi パスワード、同僚に送るリカバリーコード、閲覧者が多すぎるチケットに貼るメモなどです。「チャットでそのまま送ればいいか」を、盗み見されても読まれない方法に置き換えます。
シークレットマネージャーではありません。何も保存せず、アクセスできる人を管理せず、誰が何を復号したかを記録せず、鍵をローテーションせず、送った秘密を取り消すこともできません。アプリケーションの認証情報、本番環境の鍵、チームで共有するものは、きちんとしたシークレットマネージャーか、共有機能のあるパスワードマネージャーに置くべきです。また、暗号化したテキストは、後でパスワードを知った人なら誰でも、いつまでも復号できることを忘れないでください。
正確な形式
パスワードモードの出力は次のとおりです。
Base64( salt[16] ‖ iv[12] ‖ ciphertext ‖ tag[16] )
- 鍵:UTF-8 のパスワードに対し、16 バイトのソルトと 310,000 回の反復で PBKDF2-HMAC-SHA256 を適用し、32 バイトを得ます。
- 暗号方式:12 バイトの IV、128 ビットのタグ、関連データなしの AES-256-GCM。
- 乱数:暗号化のたびに
crypto.getRandomValuesから新しいソルトと IV を生成します。
暗号文の長さは UTF-8 のメッセージとちょうど同じなので、ブロブのオーバーヘッドは 44 バイトです。33 バイトのメッセージは 77 バイト、つまり Base64 で 104 文字になります。バージョンバイトはなく、反復回数も保存されません。変更した場合、受け取る人が同じ値を入力しないと、パスワードの誤りと同じエラーで復号に失敗します。
生の鍵モードでは PBKDF2 の手順がなくなり、出力は Base64( iv[12] ‖ ciphertext ‖ tag[16] ) になります。暗号化には、Base64 か 16進数で指定した 16、24、32 バイトの鍵を使います。ランダムな鍵を生成で鍵を作れます。Chrome と Edge は 192 ビットの AES 鍵に対応しておらず、ツールは黙って失敗せずにその旨を表示します。128 ビットか 256 ビットを使ってください。
Python や Node.js での復号
受け取る人がこのサイトを使う必要はありません。Python と cryptography パッケージ(pip install cryptography)なら次のとおりです。
import base64, os
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from cryptography.hazmat.primitives import hashes
def _key(password, salt):
return PBKDF2HMAC(algorithm=hashes.SHA256(), length=32, salt=salt,
iterations=310000).derive(password.encode("utf-8"))
def decrypt(b64, password):
data = base64.b64decode(b64)
salt, iv, ct = data[:16], data[16:28], data[28:]
return AESGCM(_key(password, salt)).decrypt(iv, ct, None).decode("utf-8")
def encrypt(text, password):
salt, iv = os.urandom(16), os.urandom(12)
ct = AESGCM(_key(password, salt)).encrypt(iv, text.encode("utf-8"), None)
return base64.b64encode(salt + iv + ct).decode("ascii")
AESGCM.decrypt はタグが暗号文の末尾にあることを前提としており、この形式もそこにタグを置いています。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");
}
このページで作ったブロブはどちらの関数でも復号でき、encrypt() で作ったブロブはこのページで復号できます。URLセーフで出力した場合、Node の Buffer.from(b64, "base64") はそのまま読めます。Python では base64.urlsafe_b64decode(b64 + "=" * (-len(b64) % 4)) を使ってください。なお、openssl enc は GCM に対応していないので、ここでは使えません。Base64 の扱いについては Python と Node.js のページで詳しく説明しています。
よくある質問
Base64 エンコードだけでテキストを守れますか?
いいえ。Base64 はバイトの書き方を変えるだけで、鍵なしで誰でもデコードできます。このツールはまず AES で暗号化し、Base64 は暗号文を貼り付け可能なテキストにするためだけに使います。詳しくは Base64 は暗号化ではないをご覧ください。
同じテキストを暗号化しても毎回出力が違うのはなぜですか?
実行のたびに、新しいランダムな 16 バイトのソルトと 12 バイトの IV を使うからです。これは意図どおりの動作です。同じメッセージから同じ暗号文ができてはならず、AES-GCM では同じ鍵で IV を再利用してはいけません。
パスワードはどれくらい強くする必要がありますか?
310,000 回の PBKDF2 は推測を遅くしますが、短いパスワードやよくあるパスワードは救えません。ランダムな単語を 5 つ以上並べたような、長くランダムなパスフレーズを使い、暗号文とは別の経路で送ってください。
このツールでファイルを暗号化できますか?
できません。暗号化できるのはテキストだけです。ファイルには age や gpg などの専用ツールを使ってください。
ツールが使う AES のモードと鍵長は何ですか?
パスワードモードでは、GCM モードの AES-256 と 128 ビットの認証タグを使います。生の鍵モードでは、鍵長は入力した鍵に従い、128、192、256 ビットのいずれかです。