我正在使用 webcrypto API 并拥有存储为
UInt8Array
的有效 Ed25519 私钥。
我想使用
KeyPair
中的私钥。这是我迄今为止的尝试:
import { webcrypto } from "node:crypto";
const RANDOM_PRIVATE_KEY_DO_NOT_USE = new Uint8Array([
144, 194, 221, 213, 246, 54, 246, 208, 227, 91, 76, 237, 35, 137, 98, 221, 82,
87, 49, 240, 137, 166, 174, 39, 208, 143, 252, 120, 182, 49, 102, 139, 134,
105, 228, 183, 34, 22, 11, 174, 73, 2, 12, 84, 231, 64, 186, 51, 148, 2, 41,
156, 137, 53, 56, 50, 0, 0, 183, 231, 67, 157, 149, 110,
]);
async function privateKeyBytesToKeyPair(
privateKeyBytes: Uint8Array
): Promise<CryptoKeyPair> {
// Import the private key
const privateKey = await webcrypto.subtle.importKey(
"raw",
privateKeyBytes.buffer,
{
name: "Ed25519",
},
true,
// These DO match the 'Algortihm Matrix' section of the WebCrypto API
// See https://nodejs.org/api/webcrypto.html#subtleimportkeyformat-keydata-algorithm-extractable-keyusages
// However this fails with "Unsupported key usage for a Ed25519 key"
["sign", "verify"]
);
const keyPair: CryptoKeyPair = {
publicKey: "TODO", // The private key is not enough to generate the public key, why do I need this?
privateKey,
};
return keyPair;
}
const keyPair = await privateKeyBytesToKeyPair(RANDOM_PRIVATE_KEY_DO_NOT_USE);
console.log("Key pair:", keyPair);
我遇到了两个问题(也许还有更多):
usages
(["sign", "verify"]
)根据密钥使用矩阵是正确的,但我的导入将失败,并显示:Unsupported key usage for a Ed25519 key
。CryptoKeyPair
时,webcrypto API 希望我在已经可以从私钥派生出公钥时指定公钥。如何从 Uint8Array 制作 webcrypto CryptoKeyPair?
根据本文件,秒。 导入密钥,Ed25519 支持的公钥格式为 spki、jwk 和 raw,私钥支持格式为 pkcs8 和 jwk。因此,您可以以 raw 格式导入公钥,但对于私钥,您必须将其转换为 jwk 或 pkcs8 格式。
您发布的私钥大小为 64 字节,因此由原始 32 字节私钥和原始 32 字节公钥串联而成。
PKCS#8 格式的私钥由前缀 302e020100300506032b657004220420 后跟 32 字节原始私钥组成。
这允许您导入 pkcs8 格式的私钥和 raw 格式的公钥,如下所示:
import { webcrypto } from "node:crypto";
const privateKey = await webcrypto.subtle.importKey(
"pkcs8",
Buffer.from("302e020100300506032b65700422042090c2ddd5f636f6d0e35b4ced238962dd525731f089a6ae27d08ffc78b631668b", "hex"),
{name: "Ed25519"},
true,
["sign"]
);
const publicKey = await webcrypto.subtle.importKey(
"raw",
Buffer.from("8669e4b722160bae49020c54e740ba339402299c893538320000b7e7439d956e", "hex"),
{name: "Ed25519"},
true,
["verify"]
);
const CryptoKeyPair = {
privateKey,
publicKey
};