Error message
InvalidAccessError: Unable to use this key to verify
Node's wording, reproduced on Node 26 (sign gives "Unable to use this key to sign"). Browsers phrase it differently — e.g. Chrome's "key.usages does not permit this operation" — but the DOMException name InvalidAccessError is the same everywhere.
WebCrypto crypto.subtle.sign / verify — browsers & Node
What it means
The key object you passed is not allowed to perform this operation: its usages array does not include it, or the key class is wrong (verifying with a private key, signing with a public one), or the key belongs to a different algorithm than the call requests. The key material may be perfectly valid — its permissions or role are not.
Why it happens
usages did not include the operation at import
commonWebCrypto keys are least-privilege: importKey(..., ["verify"]) produces a key that can only verify. Importing with [] or with ["sign"] and then calling verify() fails here — usages are fixed at creation and cannot be added later.
Public/private halves swapped
commonsubtle.sign requires the private key; subtle.verify requires the public key. Passing keyPair.publicKey to sign (or privateKey to verify) is a role error the API refuses outright.
Key algorithm differs from the operation's
occasionalAn ECDH key used in an ECDSA sign call (or vice versa) fails even on the same curve — WebCrypto binds keys to the algorithm they were created for, so "one EC key for both" designs must import the material twice.
How to fix it
- 1.
Declare the usages you will need
List every intended operation when generating or importing; re-import the same material with different usages when one key serves several roles.
js const keyPair = await crypto.subtle.generateKey( { name: "ECDSA", namedCurve: "P-256" }, true, ["sign", "verify"], // privateKey gets "sign", publicKey gets "verify" ); - 2.
Route the correct half to each call
Inspect key.type and key.usages when debugging — they state exactly what the object is allowed to do.
js console.log(key.type, key.usages); // e.g. "public" ["verify"] const sig = await crypto.subtle.sign(alg, keyPair.privateKey, data); const ok = await crypto.subtle.verify(alg, keyPair.publicKey, sig, data);