如何使用 WebCryptoApi 从私钥导出公钥?

Max*_*pin 5 javascript cryptography webcrypto-api

私钥是使用椭圆曲线生成的。Web Crypto API 的SubtleCrypto接口中的方法似乎都无法从私钥派生公钥,如果我错了,请纠正我。我必须使用第三方库吗?

Top*_*aco 6

WebCrypto 是一个低级 API,只有相对较小的功能集。据我所知,没有专门的方法可以从私钥派生公钥。

但是,您可以将私有导出CryptoKey为 JWK(JSON Web 密钥),删除私有部分,然后重新导入剩余部分,从而将其变为公共CryptoKey。以下代码显示了 ECDSA 密钥的这一点:

async function getPublic(privateKey){
    const jwkPrivate = await crypto.subtle.exportKey("jwk", privateKey);    
    delete jwkPrivate.d;
    jwkPrivate.key_ops = ["verify"];
    return crypto.subtle.importKey("jwk", jwkPrivate, {name: "ECDSA", namedCurve: "P-256"}, true, ["verify"]);
}

async function test(){

    // Generate test key pair
    const keyPair = await crypto.subtle.generateKey({name: "ECDSA", namedCurve: "P-256"}, true, ["sign", "verify"]);

    // Derive public from private key
    const publicKeyFromPrivate = await getPublic(keyPair.privateKey)

    // Compare CryptoKeys
    console.log(keyPair.publicKey);
    console.log(publicKeyFromPrivate)

    // Compare keys (in JWK format)
    const jwkPublic = await crypto.subtle.exportKey("jwk", keyPair.publicKey);
    const jwkPublicFromPrivate = await crypto.subtle.exportKey("jwk", publicKeyFromPrivate);
    console.log(jwkPublic);
    console.log(jwkPublicFromPrivate);
}

(async () => {
    await test()
})();
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,原始和重建的公钥是相同的。

然而,应该提到的是,该解决方案有一个缺点:私钥必须是可导出的。

这篇文章展示了 RSA 的相同方法。