This project defines a wrapper for Elliptic Curve (EC) private and public keys.
This wrapper supports onl the three main curves listed below:
OpenSSL Curve Name | RFC-7518 (6.2.1.1) | ASN.1 OID |
---|---|---|
prime256v1 |
P-256 |
1.2.840.10045.3.1.7 |
secp384k1 |
P-256K non standard |
1.3.132.0.10 |
secp384r1 |
P-384 |
1.3.132.0.34 |
secp521r1 |
P-521 |
1.3.132.0.35 |
Both the OpenSSL names and RFC-7518 (JWA/JWK) names can be used as parameters
to the methods in the ECKey
class.
Please be aware that NodeJS (and OpenSSL) support a large number of curves
(see openssl ecparam -list_curves
for a full list), but for brevity this
implementation restricts to the three mentioned above.
PLEASE NOTE: The
P-256K
curve name (crv
parameter) used when serializing a key using thesecp384k1
curve is not standard, and NOT interoperable with other systems.See the IANA registry for all known (and interoperable) curve names.
The
P-256K
name used might change at ANY time.
To use, start importing the main ECKey
class:
const ECKey = require('ec-key');
To create a random ECKey
instance simply call the createECKey
static
method, optionally specifying a curve name (defaults to prime256v1
):
// Create a new (random) ECKey instance using the secp521r1 curve
var randomKey = ECKey.createECKey('P-521');
To import an existing private or public key, simply invoke the constructor
with a String
or a Buffer
and the format in which the key is encoded:
// Create a new ECKey instance from a base-64 spki string
var key = new ECKey('MFkwEw ... 3w06qg', 'spki');
For Buffer
s and base64-encoded String
s the constructor supports both the
pkcs8
(or rfc5208
) and spki
(or rfc5280
) formats.
Additionally, the pem
format is supported for unencoded String
s and
Buffer
s:
// Load up a PEM file and wrap it into a
var pem = fs.readFileSync('./key.pem');
var key = new ECKey(pem, 'pem');
Instances of the ECKey
class can also be created from very simple object.
For example JWKs can be used directly, and whereas in the example below the
crv
, x
and y
values will be considered, kty
and kid
will be ignored.
/// Simply create from a JWK object
var key = new ECKey({
"kty":"EC",
"crv":"P-256",
"x":"f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU",
"y":"x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0",
"kid":"Public key used in JWS spec Appendix A.3 example"
})
The following values are recognized:
curve
orcrv
: the curve type for this key, identified either by its OpenSSL or its RFC-7518 (JWA/JWK) name.
With regards to coordinates:
d
: the private d coordinate for the elliptic curve point, either as aBuffer
, or a base64-encodedString
of the coordinate's big endian representationx
: the public x coordinate for the elliptic curve point, either as aBuffer
, or a base64-encodedString
of the coordinate's big endian representationy
: the public y coordinate for the elliptic curve point, either as aBuffer
, or a base64-encodedString
of the coordinate's big endian representation
And also:
publicKey
: the uncompressed and prefixed (0x04) concatenation of the x and y public coordinates' big endian representation, as described in SEC-1 ECC section 2.3.3privateKey
: the private d coordinate for the elliptic curve point, either as aBuffer
, or a base64-encodedString
of the coordinate's big endian representation
The following enumerable properties are available for instances of ECKey
:
curve
: the EC key curve name in OpenSSL format (e.g.prime256v1
)isPrivateECKey
: a boolean indicating whther this instance represents a private or public EC key.x
: the public x coordinate's big endian representation for the elliptic curve point as aBuffer
y
: the public y coordinate's big endian representation for the elliptic curve point as aBuffer
d
: the private d coordinate's big endian representation for the elliptic curve point as aBuffer
Additionally the following properties are available, but not enumerable:
jsonCurve
: the EC key curve name in RFC-7518 format (e.g.P-256
)publicCodePoint
: the uncompressed and prefixed (0x04) concatenation of the x and y public coordinates' big endian representation, as described in SEC-1 ECC section 2.3.3.
Return this
instance if this key is a public key, or create a new ECKey
instance not including the private components of the key.
A simple shortcut for createECDH().computeSecret(otherKey)
as explained below.
Create a standard Node ECDH
object instance whose computeSecret(...)
function accepts also ECKey
(as in, this class) instances.
Create a standard Node Sign
object whose sign(...)
function is automatically populated with this instance.
hash
: the hashing function to use for generating the signature, normally one ofSHA256
,SHA384
orSHA512
.
// Create a signature of the message "the quick brown fox" with a random key
var message = "the quick brown fox";
var key = ECKey.createECKey('P-384');
var signature = key.createSign('SHA384')
.update(message)
.sign('base64');
Create a standard Node Verify
object whose verify(...)
function is automatically populated with this instance.
hash
: the hashing function to use for generating the signature, normally one ofSHA256
,SHA384
orSHA512
.
// Verify the signature calcuated above
key.createVerify('SHA384')
.update(message)
.verify(signature, 'base64');
Encode this EC key, optionally using the specified format (defaults to pem
).
Formats supported are as follows:
pem
: return aBuffer
containing theascii
represtation of the OpenSSL PEM format- equivalent to
new Buffer(key.toString('pem'), 'ascii')
and provided for convenience only
- equivalent to
rfc5951
: (private keys only) returns the encoding of this key as specified by RFC-5951pkcs8
orrfc5208
: (private keys only) returns the PKCS8 encoding of this key as specified by RFC-5208spki
orrfc5280
: (public keys only) returns the SPKI encoding of this key as specified by RFC-5280
Encode this EC key, optionally using the specified format (defaults to pem
).
Formats supported are as follows:
pem
: return the key in OpenSSL's PEM formatrfc5951
: (private keys only) returns the encoding of this key as specified by RFC-5951, wrapped with a header and footer as outlined in section 4pkcs8
orrfc5208
: (private keys only) returns the PKCS8 encoding of this key as specified by RFC-5208 encoded in base64spki
orrfc5280
: (public keys only) returns the SPKI encoding of this key as specified by RFC-5280 encoded in base64
Formats this ECKey
as a JSON Web Key as specified by
RFC-7517.
Please note that his function will also be called by the JSON.stringify(...)
function.
// Convert a PEM to a JWK in one easy step
var pem = `-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgzr+Twxehecu0VYoC
XUBL1Z4h3H28gPnJ5MP0AcOixAOhRANCAAS6pMWMMndZxOPSC9ui6sUUbmeK6dIi
k3ZwTmm0SE7G+tYon5C57aVek5qH4y4OipbSLfbsIQuOkt0G8Vu1KZ3u
-----END PRIVATE KEY-----`;
var key = new ECKey(pem, 'pem');
var jwk = JSON.stringify(key, null, 2);
console.log(jwk);
// This will result in the following output:
// {
// "kty": "EC",
// "crv": "P-256",
// "x": "uqTFjDJ3WcTj0gvbourFFG5niunSIpN2cE5ptEhOxvo",
// "y": "1iifkLntpV6TmofjLg6KltIt9uwhC46S3QbxW7Upne4",
// "d": "zr-Twxehecu0VYoCXUBL1Z4h3H28gPnJ5MP0AcOixAM"
// }