AES-256-CBC
AES-256-CBCでは、暗号化と復号する際に以下が必要になる。
- 256 bitの秘密のkey
- 16 bitのiv(初期化ベクトル, initialization vector. 暗号化対象ごとに変える)
秘密のkey
AES-256-CBCではkeyは同じ256 bitである必要がある。
256 bit / 8 = 32 byte -> 32文字のランダムな英数字を用意すればいい。ハイフンなしのUUIDで用意するのが簡単。
$ python3 -c 'import uuid; print(uuid.uuid4().hex)'
e61454eb27a145019a5f9696c912ad62
iv
AES-256-CBCではivは16 bitである必要がある。
crypto.randomBytes(16)
でランダムなivを取得できる。
Node.jsのCryptoを使った実装サンプル
処理概要
Cipher
を使って引数に渡したUTF-8
文字列を暗号化する。暗号化したバイナリはBASE64
で文字列にエンコードし、同じくBASE64
でエンコードしたiv
と任意の区切り文字($
)で繋ぎ合わせてDBに保存する。
後日、DBから取得したデータ([iv]$[暗号化データ]
)を$
で区切り、iv
と暗号化データに分割して、Decipher
を使って復号する。
※DBアクセスコードは実際には省略する
コード
環境: Node.js v16.13.1
import crypto from 'crypto'
// 秘匿情報のため本来はプログラム上にベタがきしてはいけないもの
const key = 'e61454eb27a145019a5f9696c912ad62';
const algorithm = 'aes-256-cbc';
const delimiter = '$';
const encode = (originalText) => {
const iv = crypto.randomBytes(16);
const cipher = crypto.createCipheriv(algorithm, key, iv);
const encrypted = cipher.update(originalText, 'utf8', 'base64') +
cipher.final('base64');
const ivWithEncrypted = iv.toString('base64') + delimiter + encrypted;
return ivWithEncrypted;
}
const decrypt = (ivWithEncrypted) => {
const [iv, encrypted] = ivWithEncrypted.split(delimiter);
const decipher = crypto.createDecipheriv(algorithm, key, Buffer.from(iv, 'base64'));
const decrypted = decipher.update(encrypted, 'base64', 'utf8') +
decipher.final('utf8');
return decrypted;
}
const email = '[email protected]';
const emailEncrypted = encode(email);
// emailEncryptedをDBに保存して処理終了
console.log(emailEncrypted);
// 後日、emailEncryptedをDBから取得して、復号する
console.log(decrypt(emailEncrypted));
以上のファイルをcrypto.mjs
とすると、node crypto.mjs
で実行した結果は以下のようになる。1行目は毎回変わる。
$ node crypto.mjs
8+ZWyRdlpkpQVqdKY3g6pw==$qd5wGkj/nGLRNa77HQM5IWixdiMxw4sHcRMrzBCaQHw=
[email protected]