はじめに
今回はJavaScriptを使って、AESで暗号化・復号を行います。
AESキーは、任意のパスフレーズをもとに生成します。
パスフレーズで暗号・復号を行うことにより、実戦的に使えると思います。
是非、参考にしてみてください。
Evernoteのテキスト暗号化
Evernoteにはテキスト暗号化機能があり、AESで暗号化を行っています。
その仕組みや実際のソースコードについては、以下の記事で解説していますので参考にしてみてください。
暗号化の仕組み
今回はAESで暗号化します。
Advanced Encryption Standard (AES) は、アメリカが2001年に標準暗号として定めた共通鍵暗号アルゴリズムである。アメリカ国立標準技術研究所(NIST)が公募し、Rijndael(ラインダール)がAESとして採用された。
https://ja.wikipedia.org/wiki/Advanced_Encryption_Standard
Evernoteの仕組みも同じですが、今回は以下のように暗号化・復号を行う実装をします。
また暗号化を行う際に、毎回同じ値にならないように対応します。
(ソルト・初期ベクトル)
実装
CryptoJS
JavaScriptで暗号・復号しますが、ライブラリにCryptoJSを使用します。
暗号化
CryptoJSをCDNを使って読み込みます。
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/core.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/enc-base64.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/cipher-core.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/sha256.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/sha1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/aes.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/hmac.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/pbkdf2.min.js"></script>
ソルトと初期ベクトルをランダムに生成します。
// ソルト
const salt = CryptoJS.lib.WordArray.random(128 / 8);
// 初期ベクトル
const iv = CryptoJS.lib.WordArray.random(128 / 8);
PBKDF2を使用して、AESキーを生成します。
const passPhrase = "password123";
...
// AESキーの生成(128bit、5万回)
const key = CryptoJS.PBKDF2(passPhrase, salt, {
keySize: 128 / 32,
iterations: 50000,
hasher: CryptoJS.algo.SHA256,
});
生成したAESキーを使い、AES(128bit)で暗号化します。
// AESキーで暗号化
const encrypted = CryptoJS.AES.encrypt(targetText, key, {
iv: iv,
});
// 暗号化されたテキスト
console.log(encrypted.toString());
暗号化されたテキストは以下のように表示されました。
f/1TkgxPBqfG02a3Ua/a0NWUoMiQfwyUd0km9jEuD4quuwcvloHuyIRAeXuF23ESgtH3ywSL5pv0gwQlvEdvIg==
復号
今度は復号を行います。
復号するためには、暗号化する際に使用した以下の情報が必要です。
AESキーの生成は暗号化と同じで、パスフレーズをもとに行います。
const passPhrase = "password123";
...
// AESキーの生成(128bit、5万回)
const key = CryptoJS.PBKDF2(passPhrase, salt, {
keySize: 128 / 32,
iterations: 50000,
hasher: CryptoJS.algo.SHA256,
});
AESキーと初期ベクトルを使い、復号できます。
// AESキーで復号
const decrypted = CryptoJS.AES.decrypt(encrypted, key, {
iv: iv,
});
全容
暗号と復号の処理を分けて実装しました。
ポイントなのは、暗号化に使用した情報をもとに復号する必要があります。
<html>
<head>
<meta charset="utf-8" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/core.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/enc-base64.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/cipher-core.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/sha256.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/sha1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/aes.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/hmac.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/pbkdf2.min.js"></script>
<script>
// 暗号化
function encrypt(text, pass) {
// ソルト
const salt = CryptoJS.lib.WordArray.random(128 / 8);
// 初期ベクトル
const iv = CryptoJS.lib.WordArray.random(128 / 8);
// AESキーの生成(128bit、5万回)
const key = CryptoJS.PBKDF2(pass, salt, {
keySize: 128 / 32,
iterations: 50000,
hasher: CryptoJS.algo.SHA256,
});
// AESキーで暗号化
const encrypted = CryptoJS.AES.encrypt(text, key, {
iv: iv,
});
return {
salt: salt,
iv: iv,
encrypted: encrypted,
};
}
// 復号
function decrypt(encryptedData, pass) {
// AESキーの生成(128bit、5万回)
const key = CryptoJS.PBKDF2(pass, encryptedData.salt, {
keySize: 128 / 32,
iterations: 50000,
hasher: CryptoJS.algo.SHA256,
});
// AESキーで復号
const decrypted = CryptoJS.AES.decrypt(encryptedData.encrypted, key, {
iv: encryptedData.iv,
});
return decrypted.toString(CryptoJS.enc.Utf8);
}
const targetText = "暗号化したいテキスト";
const passPhrase = "password123";
// 暗号化
const encryptedData = encrypt(targetText, passPhrase);
// 復号
const decrypted = decrypt(encryptedData, passPhrase);
// 復号されたテキスト
console.log(decrypted.toString(CryptoJS.enc.Utf8));
</script>
</head>
<body></body>
</html>
TXT-Crypter
今回解説した仕組みと同じですが、暗号・復号を簡単に行うことができるサービスを作成しました。
Notionを使ってパスワード管理を行う例は、以下の記事を参考にしてください。
さいごに
今回はJavaScriptを使って、AESで暗号化・復号を行いました。
暗号・復号の仕組みについて参考にしてみてください。
コメント