私はWeb暗号化APIで生成されたRSA秘密キーをパスワードで保護しようとしていました。これを行うには、私が最初に AESキーでRSA秘密キーをラップしてアンラッピングする
- は、その後、私はその後、私はSTEP2からAESキーでSTEP1からのRSA秘密鍵をラップするパスワード
- からAES対称鍵を導出します。
- 私は終わりだとき、私はすぐに私はそれを
のラップを解除しようとunwrap
方法にこれらのすべてを渡すことで、これは働いていた検証しようとするここでは、コードです:
<html>
<script>
function wrap(password) {
var iterations = 1000000;
// Utility function
var stringToByteArray = function(s){
if ("TextEncoder" in window) {
encoder = new window.TextEncoder;
return encoder.encode(s);
}
var result = new Uint8Array(s.length);
for (var i=0; i<s.length; i++){
result[i] = s.charCodeAt(i);
}
return result;
}
var saltBytes = stringToByteArray("NaCl");
var passphraseBytes = stringToByteArray(password);
return crypto.subtle.generateKey({
name: "RSA-OAEP",
modulusLength: 2048,
publicExponent: new Uint8Array([1, 0, 1]),
hash: {name: "SHA-256"}
}, true, ["encrypt", "decrypt"]).then(function(keyPair) {
return crypto.subtle.importKey(
"raw", passphraseBytes, {name: "PBKDF2"}, false, ["deriveKey"]
).then(function(baseKey) {
return window.crypto.subtle.deriveKey(
{name: "PBKDF2", salt: saltBytes, iterations: iterations, hash: "SHA-1"},
baseKey,
{name: "AES-CBC", length: 256},
false,
["encrypt", "decrypt", "wrapKey", "unwrapKey"]
).then(function(wrapperKey) {
var iv = crypto.getRandomValues(new Uint8Array(16));
return crypto.subtle.wrapKey(
"pkcs8",
keyPair.privateKey,
wrapperKey,
{name: "AES-CBC", iv: iv }
).then(function(wrappedKey) {
return {
iv: iv,
wrapper: wrapperKey,
wrapped: wrappedKey
}
})
});
}).catch(function(err) {
console.log(err);
});
})
}
function unwrap(account) {
console.log(account);
crypto.subtle.unwrapKey(
"pkcs8",
account.wrapped,
account.wrapper,
{
name: "AES-CBC",
iv: account.iv
},
{
name: "RSA-OAEP",
modulusLength: 2048,
publicExponent: new Uint8Array([1, 0, 1]),
hash: {name: "SHA-256"}
},
true,
['decrypt', 'encrypt']
).then(function(privateKey) {
console.log("unwrapped = ", privateKey);
}).catch(function(e) {
console.log(e)
})
}
// Finally I call "wrap" and then "unwrap"
wrap("password").then(unwrap)
</script>
</html>
しかし、コードは動作しません。ラッピングコードはエラーを投げず、キーが生成されているようです(ただし、これらが有効かどうかはわかりませんが)。私はunwrapKey
メソッドを実行しようとする。しかし、私は次のエラーを取得する:私はこの仕事を得ることができないので
DOMException: Cannot create a key using the specified key usages.
私は、最後の24時間の私の髪を引っ張ってきました。誰も問題を見つけることができますか?これは完璧に自己完結型のコードなので、コピーしてHTMLファイルに貼り付けてブラウザで開くことで試してみることができます。
あなたがMozillaのドキュメントに基づいて話している場合は、私は彼らのドキュメントが不完全で、時にはWebCrypto APIの少なくとも誤解であることを学んだので、それはWebCryptoのAPIに来るとき、私は彼らを信用していません。元のW3Cの提案にはそのような制限はなく、仕様によれば、それは単なる暗号化メカニズムだという。また、私はこの質問をして以来、私はこれを行うライブラリを見つけたhttps://github.com/safebash/OpenCrypto – Vlad
確かにそれはMozillaのドキュメントであり、確かにほとんどの(すべて?)現在の主要なブラウザの状態です。また、W3Cは、あなたが言うように、ラッピングを制限しません。しかし、上記は開発者向けのbroswer APIを通じて利用できるものです。あなたの要件を実装するソリューションが見つかりました。すべて:MBCの悪い実装...(メジャーブラウザーコンソーシアム)...新年あけましておめでとうございます! –