我需要使用零依赖性ECDSA
生成一个
确定性集
javascript
密钥,为此我用原始字节生成一个pkcs8
密钥,然后将其导入为ECDSA
私钥。这在逻辑上是否可能,如果是,下面的代码有什么问题,因为它在导入调用期间给了我DataError错误。
// Example function to convert derived bits to a PKCS#8 formatted key and import it
function convertRawKeyToPKCS8(rawKey, curveOid) {
// PKCS#8 header for ECDSA with the chosen curve OID
const pkcs8Header = [
0x30, 0x81, 0x87, // SEQUENCE (header, total length)
0x02, 0x01, 0x00, // INTEGER (version 0)
0x30, 0x13, // SEQUENCE (AlgorithmIdentifier header)
0x06, 0x07, // OBJECT IDENTIFIER (1.2.840.10045.2.1 - ecPublicKey OID)
0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01,
0x06, 0x08, // OBJECT IDENTIFIER for curve (this is curve specific, provided as parameter)
...curveOid,
0x04, 0x6d, // OCTET STRING (privateKey length follows)
0x30, 0x6b, // SEQUENCE
0x02, 0x01, 0x01, // INTEGER (version 1)
0x04, 0x20 // OCTET STRING (private key length, 32 bytes for P-256)
];
// Append the raw private key bytes
const pkcs8Key = new Uint8Array(pkcs8Header.length + rawKey.length);
pkcs8Key.set(pkcs8Header);
pkcs8Key.set(rawKey, pkcs8Header.length);
return pkcs8Key;
}
// Example OIDs for different elliptic curves:
const OID_P256 = [0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07]; // P-256 curve OID
// Example raw ECDSA private key for P-256 (32 bytes):
const rawPrivateKey = new Uint8Array([
0x93, 0x6a, 0x62, 0x91, 0x62, 0xa9, 0xba, 0x46,
0x0c, 0x12, 0xfa, 0xb7, 0xdb, 0xe0, 0x2f, 0x91,
0x52, 0xfa, 0xd2, 0xda, 0x47, 0x9a, 0x7d, 0xf2,
0xbe, 0xab, 0xaa, 0x04, 0x48, 0x67, 0x6b, 0xa1
]);
// Generate the PKCS#8 key
const pkcs8Key = convertRawKeyToPKCS8(rawPrivateKey, OID_P256);
// Log the resulting PKCS#8 key as a hexadecimal string for display (optional)
console.log(Array.from(pkcs8Key).map(b => b.toString(16).padStart(2, '0')).join(''));
// Use the SubtleCrypto API to import the PKCS#8 key
async function importECDSAPrivateKey(pkcs8Key) {
const privateKey = await crypto.subtle.importKey(
"pkcs8",
pkcs8Key.buffer,
{
name: "ECDSA",
namedCurve: "P-256",
},
true, // Extractable
["sign"] // Key usage
);
return privateKey;
}
// Example usage
importECDSAPrivateKey(pkcs8Key).then(privateKey => {
console.log('Private key imported:', privateKey);
}).catch(console.error);
有两个问题:
当包含公钥时,第一个序列长度仅为0x87。由于您没有添加它,因此 ASN.1 结构无效。
解决方案很简单:添加公钥:
// Example function to convert derived bits to a PKCS#8 formatted key and import it
function convertRawKeyToPKCS8(rawPrivateKey, rawPublicKey, curveOid) {
// PKCS#8 header for ECDSA with the chosen curve OID
let pkcs8Key = [
0x30, 0x81, 0x87, // SEQUENCE (header, total length)
0x02, 0x01, 0x00, // INTEGER (version 0)
0x30, 0x13, // SEQUENCE (AlgorithmIdentifier header)
0x06, 0x07, // OBJECT IDENTIFIER (1.2.840.10045.2.1 - ecPublicKey OID)
0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01,
0x06, 0x08, // OBJECT IDENTIFIER for curve (this is curve specific, provided as parameter)
...curveOid,
0x04, 0x6d, // OCTET STRING (privateKey length follows)
0x30, 0x6b, // SEQUENCE
0x02, 0x01, 0x01, // INTEGER (version 1)
0x04, 0x20, // OCTET STRING (private key length, 32 bytes for P-256)
...rawPrivateKey,
0xa1, 0x44, // [1] (tag)
0x03, 0x42, // BIT STRING (public key length, 66 bytes for P-256)
...rawPublicKey,
];
return new Uint8Array(pkcs8Key);
}
// Example OIDs for different elliptic curves:
const OID_P256 = [0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07]; // P-256 curve OID
// Example raw ECDSA private key for P-256 (32 bytes):
const rawPrivateKey = [
0x17, 0x4f, 0xa3, 0x30, 0xdb, 0xd7, 0xf9, 0x66,
0xee, 0xb2, 0x36, 0xcc, 0xbc, 0x29, 0xb0, 0x25,
0x5a, 0xd2, 0xcf, 0x0c, 0x91, 0x06, 0x9a, 0x9f,
0x33, 0x53, 0x37, 0x24, 0x87, 0x8e, 0x03, 0x2b,
];
const rawPublicKey = [
0x00, 0x04, 0x87, 0x44, 0x7e, 0xc5, 0xc8, 0xff,
0xfb, 0x77, 0xf7, 0x24, 0x0d, 0xdd, 0x8b, 0xa2,
0x03, 0x8b, 0xf9, 0x7c, 0x3b, 0x86, 0x4a, 0xb8,
0x4b, 0xb1, 0xea, 0x3d, 0x3a, 0xe2, 0x2f, 0xca,
0xbf, 0xb1, 0xfe, 0xbd, 0xf4, 0xda, 0x4b, 0xfd,
0x12, 0x30, 0x79, 0xe2, 0x8b, 0x3b, 0x35, 0xae,
0x22, 0x2b, 0x06, 0xd2, 0xd2, 0x26, 0x24, 0x6f,
0x95, 0x5a, 0xa2, 0x51, 0x87, 0x4c, 0x42, 0x41,
0xdd, 0x67,
]
// Generate the PKCS#8 key
const pkcs8Key = convertRawKeyToPKCS8(rawPrivateKey, rawPublicKey, OID_P256);
// Log the resulting PKCS#8 key as a hexadecimal string for display (optional)
console.log(Array.from(pkcs8Key).map(b => b.toString(16).padStart(2, '0')).join(''));
// Use the SubtleCrypto API to import the PKCS#8 key
async function importECDSAPrivateKey(pkcs8Key) {
const privateKey = await crypto.subtle.importKey(
"pkcs8",
pkcs8Key.buffer,
{
name: "ECDSA",
namedCurve: "P-256",
},
true, // Extractable
["sign"] // Key usage
);
return privateKey;
}
// Example usage
importECDSAPrivateKey(pkcs8Key).then(privateKey => {
console.log('Private key imported:', privateKey);
}).catch(console.error);