<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body>
<script>
let intermediateKey;
let publicKey;
let privateKey;
let wrappedKey;
let iv;
async function rsaKeyPair() {
let keyPair = await crypto.subtle.generateKey({
name: "RSA-OAEP",
modulusLength: 4096,
publicExponent: new Uint8Array([1, 0, 1]),
hash: "SHA-256",
},
true, ["wrapKey", "unwrapKey"]
);
publicKey = keyPair.publicKey;
privateKey = keyPair.privateKey;
}
async function encrypt(secret) {
// generating random intermediate key to encrypt and decrypt the secret
intermediateKey = await crypto.subtle.generateKey({
name: "AES-GCM",
length: 256
},
true, ["encrypt", "decrypt"]
);
// encrypt secret
// ...
// wrap intermediate key (export + encrypt) intermediateKey using publicKey.
iv = crypto.getRandomValues(new Uint8Array(12));
wrappedKey = await crypto.subtle.wrapKey(
"jwk",
intermediateKey,
publicKey, {
name: "AES-GCM",
iv: iv
}
);
}
async function decrypt(cipher) {
// unwrap (decrypt + import) aes key using private key.
intermediateKey = await crypto.subtle.unwrapKey(
"jwk",
wrappedKey,
privateKey, {
name: "AES-GCM",
iv: iv
}, {
name: "AES-GCM"
},
false, ["encrypt", "decrypt"]
);
// decrypt the cipher
// ...
}
async function solve() {
// generate rsa-keypairs
await rsaKeyPair();
// encrypt secret
const cipher = await encrypt("secret");
// decrypt cipher
await decrypt(cipher);
}
solve();
</script>
</body>
</html>
生成 RSA-OAEP 密钥对(根据http://www.w3.org/TR/WebCryptoAPI/#algorithm-overview。)
当用户创建秘密时,秘密使用 AES-GCM-256 和随机生成的中间密钥进行加密。最后,这个中间密钥与用户的公钥一起包装。
最后解开中间密钥和解密。
该错误是在展开中间密钥期间生成的。