使用 public RSA 密钥包装对称密钥会导致 DOMException (InvalidAccessError)
Wrapping symmtric key with public RSA key causes DOMException (InvalidAccessError)
我正在尝试使用 Web Crypto API 包装对称密钥,但出现错误:
DOMException: key.usages does not permit this operation
对使用 Web Crypto API 还是很陌生,所以我不完全理解为什么这是一个问题。我想用 Public 密钥包装对称密钥,然后用我的私钥打开它。
我将问题提取到一个小代码沙箱中https://codesandbox.io/s/cranky-driscoll-v0itr?file=/src/index.ts
或者,可以使用以下步骤重现该问题。
生成加密密钥对(我这里用的是RSA)
生成对称密钥
通话
window.crypto.subtle.wrapKey(
"raw",
fileKey,
publicKey,
publicKey.algorithm.name
);
这是来自沙盒的完整代码:
sync function foo() {
try {
const cryptoKeyPair = await window.crypto.subtle.generateKey(
{
name: "RSA-OAEP",
modulusLength: 4096,
publicExponent: new Uint8Array([1, 0, 1]),
hash: "SHA-256"
},
true,
["encrypt", "decrypt"]
);
const publicKey = cryptoKeyPair.publicKey;
const fileKey = await window.crypto.subtle.generateKey(
{ name: "AES-GCM", length: 256 },
true,
["encrypt", "decrypt"]
);
const wrapKeyResult = await window.crypto.subtle.wrapKey(
"raw",
fileKey,
publicKey,
publicKey.algorithm.name
);
// ^^ here we get error: DOMException: key.usages does not permit this operation
/**
* {
* code: 15
* message: "key.usages does not permit this operation"
* name: "InvalidAccessError"
* }
*/
console.log("Wrapped Key", wrapKeyResult);
} catch (error) {
console.error("something went wrong", error);
throw error;
}
foo()
.then((res) => {
console.log("I succeeded!");
})
.catch((error) => console.log("I failed with ", error));
在generateKey()
the wrong key usages中应用。正确的是 wrapKey
和 unwrapKey
,因为 RSA 密钥对用于 wrapping/unwrapping 对称 AES-GCM 密钥:
async function foo() {
try {
const cryptoKeyPair = await window.crypto.subtle.generateKey(
{
name: "RSA-OAEP",
modulusLength: 4096,
publicExponent: new Uint8Array([1, 0, 1]),
hash: "SHA-256"
},
true,
["wrapKey", "unwrapKey"] // Apply wrapKey and unwrapKey here!
);
const publicKey = cryptoKeyPair.publicKey;
const fileKey = await window.crypto.subtle.generateKey(
{ name: "AES-GCM", length: 256 },
true,
["encrypt", "decrypt"]
);
const wrapKeyResult = await window.crypto.subtle.wrapKey(
"raw",
fileKey,
publicKey,
publicKey.algorithm.name
);
console.log("Wrapped Key", new Uint8Array(wrapKeyResult));
} catch (error) {
console.error("something went wrong", error);
throw error;
}
}
foo()
.then((res) => {
console.log("I succeeded!");
})
.catch((error) => console.log("I failed with ", error));
我正在尝试使用 Web Crypto API 包装对称密钥,但出现错误:
DOMException: key.usages does not permit this operation
对使用 Web Crypto API 还是很陌生,所以我不完全理解为什么这是一个问题。我想用 Public 密钥包装对称密钥,然后用我的私钥打开它。
我将问题提取到一个小代码沙箱中https://codesandbox.io/s/cranky-driscoll-v0itr?file=/src/index.ts
或者,可以使用以下步骤重现该问题。
生成加密密钥对(我这里用的是RSA)
生成对称密钥
通话
window.crypto.subtle.wrapKey( "raw", fileKey, publicKey, publicKey.algorithm.name );
这是来自沙盒的完整代码:
sync function foo() {
try {
const cryptoKeyPair = await window.crypto.subtle.generateKey(
{
name: "RSA-OAEP",
modulusLength: 4096,
publicExponent: new Uint8Array([1, 0, 1]),
hash: "SHA-256"
},
true,
["encrypt", "decrypt"]
);
const publicKey = cryptoKeyPair.publicKey;
const fileKey = await window.crypto.subtle.generateKey(
{ name: "AES-GCM", length: 256 },
true,
["encrypt", "decrypt"]
);
const wrapKeyResult = await window.crypto.subtle.wrapKey(
"raw",
fileKey,
publicKey,
publicKey.algorithm.name
);
// ^^ here we get error: DOMException: key.usages does not permit this operation
/**
* {
* code: 15
* message: "key.usages does not permit this operation"
* name: "InvalidAccessError"
* }
*/
console.log("Wrapped Key", wrapKeyResult);
} catch (error) {
console.error("something went wrong", error);
throw error;
}
foo()
.then((res) => {
console.log("I succeeded!");
})
.catch((error) => console.log("I failed with ", error));
在generateKey()
the wrong key usages中应用。正确的是 wrapKey
和 unwrapKey
,因为 RSA 密钥对用于 wrapping/unwrapping 对称 AES-GCM 密钥:
async function foo() {
try {
const cryptoKeyPair = await window.crypto.subtle.generateKey(
{
name: "RSA-OAEP",
modulusLength: 4096,
publicExponent: new Uint8Array([1, 0, 1]),
hash: "SHA-256"
},
true,
["wrapKey", "unwrapKey"] // Apply wrapKey and unwrapKey here!
);
const publicKey = cryptoKeyPair.publicKey;
const fileKey = await window.crypto.subtle.generateKey(
{ name: "AES-GCM", length: 256 },
true,
["encrypt", "decrypt"]
);
const wrapKeyResult = await window.crypto.subtle.wrapKey(
"raw",
fileKey,
publicKey,
publicKey.algorithm.name
);
console.log("Wrapped Key", new Uint8Array(wrapKeyResult));
} catch (error) {
console.error("something went wrong", error);
throw error;
}
}
foo()
.then((res) => {
console.log("I succeeded!");
})
.catch((error) => console.log("I failed with ", error));