使用 AES 密钥包装 RSA 私钥,然后解包



我一直在尝试用密码保护使用Web Cryptography API生成的RSA私钥。为此,

  1. 我首先生成一个 RSA 密钥对
  2. 然后我从密码中派生出一个 AES 对称密钥
  3. 然后,我将步骤 1 中的 RSA 私钥与步骤 2 中的 AES 密钥包装在一起。
  4. 完成后,我尝试通过立即将所有这些传递给我尝试解开包装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 文件中并在浏览器中打开来尝试它。

您正在尝试做的是,用对称密钥包装公钥/私钥,而不是包装/解包的工作方式。

  • wrapKey,允许密钥包装对称密钥以供使用(传输、存储)在不安全的环境中。
  • unwrapKey,允许 解开对称密钥以用于使用(传输、存储)的密钥 不安全的环境。

您可以包装/解包对称密钥,但不能包装/解包公钥/私钥对(或密钥),因为包装/解包可能希望包装的密钥是对称密钥而不是非对称密钥。

SubtleCrypto.wrapKey()方法返回包装的 Promise 用于在不安全环境中使用(传输、存储)的对称密钥。 返回的包装缓冲区采用参数中给出的格式,并且 包含由给定的 give 包装键包装的键 算法。

SubtleCrypto.unwrapKey()方法返回加密密钥的承诺 对应于参数中给出的包装密钥。

最新更新