The generateKey() docs states:
extractable A boolean value indicating whether it will be possible to export the key using SubtleCrypto.exportKey() or SubtleCrypto.wrapKey().
It isn't entirely clear whether this applies to the public key in keypairs. I would not consider a public key to be a secret. But (sadly) specs don't always agree with me, and a public key is at least a 'key' by name.
The webcrypto spec includes items like:
such deserialization may expose the contents of the key material, which in some cases (such as when the [[extractable]] internal slot is false) should not be exposed to applications.
But again, it's unclear whether a public key is considered key material. I would not consider a public key to be key material. Others may disagree.
Create a file runme.js and run it with node runme.js
const keyPair = await crypto.subtle.generateKey( "Ed25519", false, // note the false for exportable ["sign", "verify"], ); const rawPublicKeyBytes = await crypto.subtle.exportKey("raw", keyPair.publicKey); console.log(`Extractable was false and we were able to export the public key:`, rawPublicKeyBytes); We can see the public key is extracted even though the CryptoKeyPair was created with exportable: false.
Is allowing a public key to be exported when the CryptoKeyPair was created with exportable: false the correct behavior?