-
Notifications
You must be signed in to change notification settings - Fork 68
Description
Summary
The current spec doesn't specify a behavior for PKC8-encoded raw private key import (when I say "raw private key" I mean "without the optional public key bytes").
Chrome and other browsers seem firmly in the camp of "this should be an error" (see this test) and throw a DataError
, while Bun and NodeJS import the key without throwing an error.
Steps to repro
Here's a snippet to reproduce the inconsistent behavior:
In Node/Bun ✅
$ node
Welcome to Node.js v20.8.0.
Type ".help" for more information.
> require("crypto")
> buffer = new Uint8Array([48,129,65,2,1,0,48,19,6,7,42,134,72,206,61,2,1,6,8,42,134,72,206,61,3,1,7,4,39,48,37,2,1,1,4,32,118,50,222,115,56,87,123,193,44,23,49,250,41,240,128,25,32,106,243,129,247,74,246,15,77,94,3,149,33,143,32,92])
> await crypto.subtle.importKey("pkcs8", buffer, { name: "ECDSA", namedCurve: "P-256" }, true, ["sign"])
CryptoKey {
type: 'private',
extractable: true,
algorithm: { name: 'ECDSA', namedCurve: 'P-256' },
usages: [ 'sign' ]
}
In browsers 🚫
> buffer = new Uint8Array([48,129,65,2,1,0,48,19,6,7,42,134,72,206,61,2,1,6,8,42,134,72,206,61,3,1,7,4,39,48,37,2,1,1,4,32,118,50,222,115,56,87,123,193,44,23,49,250,41,240,128,25,32,106,243,129,247,74,246,15,77,94,3,149,33,143,32,92])
> await crypto.subtle.importKey("pkcs8", buffer, { name: "ECDSA", namedCurve: "P-256" }, true, ["sign"])
Uncaught Error
The imported bytes above represent a P-256 private key without the public key bytes (in hex: 308141020100301306072a8648ce3d020106082a8648ce3d0301070427302502010104207632de7338577bc12c1731fa29f08019206af381f74af60f4d5e0395218f205c
). Here's a asn1js link to see the structure
@panva helped me run this case across multiple implementations, here are the results:
runtime | result |
---|---|
Bun | ✔️ |
Chromium | DataError |
Deno | DataError |
Firefox | DataError |
Node.js | ✔️ |
WebKit | DataError |
Workerd | DataError |
See nodejs/node#50174 for context