Node.js Crypto モジュールと CryptoJS による暗号化・復号化
モジュールやライブラリの整理
Crypto モジュール
まず Crytpo モジュールというのは Node.js に付属するもので、最新のブラウザでもこの crypto モジュールは導入されているらしい。
The node:crypto module provides cryptographic functionality that includes a set of wrappers for OpenSSL's hash, HMAC, cipher, decipher, sign, and verify functions.
https://nodejs.org/api/crypto.html#crypto
ただし、React や Angular などのフレームワークで開発する時は..
Crypto モジュールにしかないもの
- scryptSync()
- pbkdf2Sync()
上記は後述の CryptJS ライブラリにも crypto-browserify にも搭載されていない。pbkdf2Sync() についてはこれで暗号化しても pbkdf2() を使って復号するのは可能だった。
CryptJS
名前通りJavaScriptのスタンダードライブラリ。
Nowadays, NodeJS and modern browsers have a native Crypto module.
crypt-browserify
上記の CryptJS ライブラリの説明で書かれている、モダンブラウザに標準搭載されているというのがこの Crypto Browserify?
Here is the subset that is currently implemented:
createHash (sha1, sha224, sha256, sha384, sha512, md5, rmd160)
createHmac (sha1, sha224, sha256, sha384, sha512, md5, rmd160)
pbkdf2
pbkdf2Sync
randomBytes
pseudoRandomBytes
createCipher (aes)
createDecipher (aes)
createDiffieHellman
createSign (rsa, ecdsa)
createVerify (rsa, ecdsa)
createECDH (secp256k1)
publicEncrypt/privateDecrypt (rsa)
privateEncrypt/publicDecrypt (rsa)
暗号化と復号化のやり方
ここでは AES-256-CBC という形式での暗号化・復号化を記載。以下の4つの値が分かっていれば暗号化されたメッセージを復号できる。
const passward =
const salt =
const iv =
const encryptedMessage =
事前準備
まず Crypt モジュールは標準搭載されているので CryptJS だけインストールする必要がある。
npm i crypto-js @types/crypto-js
Encrypt with Crypto
const message = 'secret message'
const password = 'password'
const salt = crypto.randomBytes(16);
const iv = crypto.randomBytes(16)
const key: Buffer = crypto.pbkdf2Sync(password, salt, 1000, 32, 'sha256')
const cipher = crypto.createCipheriv('aes-256-cbc', key, iv)
encryptedMessage = Buffer.concat([
cipher.update(message),
cipher.final()
])
Encrypt with CryptoJS
ChatGPT出力コードで未検証。
const message = 'secret message';
const password = 'password';
const salt = CryptoJS.lib.WordArray.random(16);
const iv = CryptoJS.lib.WordArray.random(16);
const key = CryptoJS.PBKDF2(password, salt, {
keySize: 256 / 32,
iterations: 1000,
hasher: CryptoJS.algo.SHA256,
});
const encrypted = CryptoJS.AES.encrypt(message, key, {
iv: iv,
padding: CryptoJS.pad.Pkcs7,
mode: CryptoJS.mode.CBC
});
const encryptedMessage = encrypted.toString();
Decrypt with Crypto
const key: Buffer = crypto.pbkdf2Sync(password, salt, 1000, 32, 'sha256')
const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv)
decryptedMessage = Buffer.concat([
decipher.update(encryptedMessage),
decipher.final()
])
Decrypt with CrpytoJS
ChipherParams を使う方法
const key: WordArray = CryptoJS.PBKDF2(password, salt, {
keySize: 256 / 32,
iterations: 1000,
hasher: CryptoJS.algo.SHA256,
});
const cipherParams = CryptoJS.lib.CipherParams.create({
ciphertext: encryptedMessage,
iv: iv,
padding: CryptoJS.pad.Pkcs7,
});
const decryptedMessage = CryptoJS.AES.decrypt(cipherParams, key, {
iv,
});
const decryptedMessageString = decrypted.toString(CryptoJS.enc.Hex);
直接 Decrypt する方法
ChatGPT出力コードで未検証。
const decrypted = CryptoJS.AES.decrypt(encryptedMessage, key, {
iv: iv,
padding: CryptoJS.pad.Pkcs7,
mode: CryptoJS.mode.CBC
});
const decryptedMessageString = decrypted.toString(CryptoJS.enc.Utf8);
Hex, WordArray の String 変換
暗号化・復号化、両モジュール・ライブラリの相互利用する際に Hex, WordArray を String に変換する機会が多かったのでメモ。
Hex -> String
CryptoJS.enc.Hex.parse(x)
WordArray -> String
x.toString(CryptoJS.enc.Hex)?
参考文献
Discussion