Given a P-256 Elliptical Curve Diffie-Hellman Private Key (which is simply a random 256-bit integer): is it possible to import this private key into a CryptoKey object, using the window.crypto.subtle.importKey() method of the Web Crypto API – without having the public key components?

I know that it’s possible to import the private key if the public key components (which are derived from the private key component) are available as well. For example, the code below runs successfully:

window.crypto.subtle.importKey(
    "jwk", //can be "jwk" (public or private), "raw" (public only), "spki" (public only), or "pkcs8" (private only)
    {
    "crv":"P-256",
    "d":"eM8u2176zFk9bwDP_jbJqnm-TlSo6GX702D9I_1AqBU",
    "ext":true,
    "key_ops":["deriveKey","deriveBits"],
    "kty":"EC",
    "x":"5Uw_SuaGZTFAuQuDArnLEmmyp4TpHx3AlBxL4EUEzbQ",
    "y":"RO5t581VBuAKTQZVPSB__ebV6y9GCzrl8lBV2-p9BlM"
    },
    {   //these are the algorithm options
    name: "ECDH",
    namedCurve: "P-256", //can be "P-256", "P-384", or "P-521"
    },
    true, //whether the key is extractable (i.e. can be used in exportKey)
    ["deriveKey"] //"deriveKey" and/or "deriveBits" for private keys only (just put an empty list if importing a public key)
)
.then(function(key) {
    console.log(key);
})
.catch(function(err){
    console.error(err);
});

However, if only the private key component is available, without the public key components, as in the code below, the Web Crypto API throws a DOMException with the message ‘Data provided to an operation does not meet requirements’.

window.crypto.subtle.importKey(
    "jwk", //can be "jwk" (public or private), "raw" (public only), "spki" (public only), or "pkcs8" (private only)
    {
    "crv":"P-256",
    "d":"eM8u2176zFk9bwDP_jbJqnm-TlSo6GX702D9I_1AqBU",
    "ext":true,
    "key_ops":["deriveKey","deriveBits"],
    "kty":"EC"
    },
    {   //these are the algorithm options
    name: "ECDH",
    namedCurve: "P-256", //can be "P-256", "P-384", or "P-521"
    },
    true, //whether the key is extractable (i.e. can be used in exportKey)
    ["deriveKey"] //"deriveKey" and/or "deriveBits" for private keys only (just put an empty list if importing a public key)
)
.then(function(key) {
    console.log(key);
})
.catch(function(err){
    console.error(err);
});

I’ve also tried using pkcs8 format for the key, instead of JWK, but no luck there either.

The documentation for the Web Crypto API shows that it is possible to import a ECDH private key in JWK format – so, it seems that it should be possible to do so without the public key components as well (the Web Crypto API should be able to calculate the public key components, if needed, from the private key component internally, as it seems to do with the .generateKey() method). However, the importKey() method seems to only work if the public key components are included.

Am I missing something here? If not, does anyone know of a solution or workaround, short of calculating the public key components separately prior to importing, and including them with the private key component in the importKey() method (which seems overly cumbersome and unnecessary)?

2

There are 2 best solutions below

0
On

If you have the pkcs8 format you can use this:

crypto.subtle.importKey("pkcs8", [privateKeyBuffer],{name:"ECDH",namedCurve:"P-256"} , true, ["deriveKey"]);
0
On

You can always derive the public point from the private key by scalar multiplying the private key with the base point (or the generator point) of the curve you chosen. How you complete this depends on your run-time environment.