Web CryptoでJavaScriptだけでパスワードによる暗号化/復号
#Web_Crypto #WebブラウザのJavaScript #セキュリティ
やりたいこと
WebブラウザのJavaScriptだけでWeb Cryptoを使って安全にパスワードによる暗号化をしたい。
Web CryptoはWeb標準の機能で動く。
やりかた
code:js
// (base: https://jsfiddle.net/sjtgj9gj/)
// (found in: https://stackoverflow.com/a/45658748/2885946)
async function encryptThenDecrypt(salt = "the salt is this random string") {
const raw = 'this is a secret';
const password = 'mysecretpassword';
const importedPassword = await window.crypto.subtle.importKey(
"raw",
stringToUint8Array(password),
{ name: "PBKDF2" },
false,
"deriveKey"
);
const key = await window.crypto.subtle.deriveKey({
name: "PBKDF2",
salt: stringToUint8Array(salt),
iterations: 100000,
hash: "SHA-256"
},
importedPassword, {
name: "AES-GCM",
length: 128
},
false,
"encrypt", "decrypt"
);
const iv = window.crypto.getRandomValues(new Uint8Array(12));
const encrypted = await window.crypto.subtle.encrypt({
name: "AES-GCM",
iv: iv,
}, key, stringToUint8Array(raw));
const encrypted_data = new Uint8Array(encrypted);
const decrypted = await window.crypto.subtle.decrypt({
name: "AES-GCM",
iv: iv,
}, key, encrypted_data);
return Decrypted data: ${uint8ArrayToString(decrypted)};
}
function stringToUint8Array(str) {
return new TextEncoder("utf-8").encode(str);
}
function uint8ArrayToString(buffer) {
return new TextDecoder("utf-8").decode(buffer);
}
encryptThenDecrypt().then(console.log);
code:出力
Decrypted data: this is a secret
参考: javascript - WebCrypto string encryption using user-submitted password - Stack Overflow
rawが暗号化したい平文。
passwordがパスワード文字列。
window.crypto.subtle.deriveKey()にはsaltとiterationsは必須。
おそらくPBKDF2だからだと思う。
iterationsが100000というのは大きすぎるのかもしれないので要調査。
AES-GCMなので初期化ベクトルivは12バイト
AES-GCMの初期化ベクトルIVは12バイト(96ビット)が推奨。
Nipp:
https://nipp.nwtgck.org/#/es2017,promise_wait/lU9da9swFH33r7iYQW1I7TU0XerSh27tNiiDsHp7KWVVrOtEqSMF6TpeCPnvk2XH+SCMzcjicu7R+YhjCMbMYAJTooVJ4nhmcsF5gZFEis2MJrPrySwOvdgyc1VKDkLu2IZY9qaWqPNCVVGm5jGLLwdXg+GHy2HcHw4H15dXoecxs5IZ5KXMSCgJKDO9WlA6RXmPbgwMKwhuwacpgpuFAZraSzPJ1RwMaSEnfghrDyBT0pDdVOC+WzhzVHsYGCuIdHbT0RbMmEppXtPmq2a9xSyt44n5QmlCPtrxWcUEQSVsAluuzqkiU46pwKhhP+Iq8OoIvg3j99zYJE3VDyFpeKc1WwVbu7BhrEGyOSbgjz4+3n/u+7Bp8JwVBpvx2eeoxRKtgf9ikXDX5w1Xf4/WvQzWTguO7HotalhByam49SLcsgShZiSsdQIX7+tvu5kyM7WqT1/vzvuDK9+hbRMxXyhNyEdt8R4cRbl7eDr/8ulbl6VAOSGrdtEf7uvkrDDYjM8+StfT74HPsRlf7Cq8sZc9mY1IIJZwC5WQXFWR46hogvSdWWD+kxUlmkBiBXttL/qhk2jetybIrQyrmKAjMVOOqcCopQVNrZOlxDKxfz1vevCGqx4Y0kJOUrVnrll10v0XZ8RshKOs3f6wNMd/Ct3S/i/0YSTnq5FKLeH1vrOtVwm8W5dd1FQ9ubZBly3cvN54G8/LS5mRUBKMI6Rqr5+FQljvLCRWkOJvepCZ4qgDv6T8fOiHETrA8Q9FTyQYl3mOp3Vtg0Nd7oDtEydtreoC6RRlWzgI/wA=
hr.icon
楕円曲線ディフィー・ヘルマン鍵共有を使った暗号化/復号なら、「Web Cryptoで楕円曲線ディフィー・ヘルマン鍵共有して、暗号化 & 復号」。