Elliptic Curve Keys
This project defines a wrapper for Elliptic Curve (EC) private and public keys.Randomly generated keys Instantiating from encoded keys Instantiating with objects
asPublicECDHCrypto()
computeSecret(otherKey)
createECDH()
createSign(hash)
createVerify(hash)
doSign(hash) Not PEM format
doVVerify(hash, data) Not PEM format
toBuffer(format)
toString(format)
toJSON()
Curves
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
ECDHCrypto
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: TheP-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.
TheP-256K
name used might change at ANY time.
Basic construction
To use, start importing the mainECDHCrypto
class:const ECDHCrypto = require('ecdh-crypto');
Randomly generated keys
To create a randomECDHCrypto
instance simply call the createECDHCrypto
static
method, optionally specifying a curve name (defaults to prime256v1
):// Create a new (random) ECDHCrypto instance using the secp521r1 curve
var randomKey = ECDHCrypto.createECDHCrypto('P-256');
Instantiating from encoded keys
To import an existing private or public key, simply invoke the constructor with aString
or a Buffer
and the format in which the key is encoded:// Create a new ECDHCrypto instance from a base-64 spki string
var key = new ECDHCrypto('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 ECDHCrypto(pem, 'pem');
Instantiating with objects
Instances of theECDHCrypto
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 ECDHCrypto({
"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
With regards to coordinates:
d
: the private d coordinate for the elliptic curve point, either as a
Buffer
, or a base64-encoded String
of the coordinate's big endian
representationx
: the public x coordinate for the elliptic curve point, either as a
Buffer
, or a base64-encoded String
of the coordinate's big endian
representationy
: the public y coordinate for the elliptic curve point, either as a
Buffer
, or a base64-encoded String
of the coordinate's big endian
representationAnd also:
publicKey
: the uncompressed and prefixed (0x04) concatenation of
privateKey
: the private d coordinate for the elliptic curve point,
Buffer
, or a base64-encoded String
of the coordinate's big
endian representationECDHCrypto properties
The following enumerable properties are available for instances ofECDHCrypto
:curve
: the EC key curve name in OpenSSL format (e.g.prime256v1
)isPrivateECDHCrypto
: a boolean indicating whther this instance represents
x
: the public x coordinate's big endian representation for the
Buffer
y
: the public y coordinate's big endian representation for the
Buffer
d
: the private d coordinate's big endian representation for the
Buffer
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
ECDHCrypto functions
asPublicECDHCrypto()
Return this
instance if this key is a public key, or create a new ECDHCrypto
instance not including the private components of the key.computeSecret(otherKey)
A simple shortcut for createECDH().computeSecret(otherKey)
as explained below.createECDH()
Create a standard Node ECDH
object instance whose computeSecret(...)
function accepts also ECDHCrypto
(as in, this class) instances.createSign(hash)
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
SHA256
, SHA384
or SHA512
.// Create a signature of the message "the quick brown fox" with a random key
var message = "the quick brown fox";
var key = ECDHCrypto.createECDHCrypto('P-384');
var signature = key.createSign('SHA384')
.update(message)
.sign('base64');
createVerify(hash)
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
SHA256
, SHA384
or SHA512
.// Verify the signature calcuated above
key.createVerify('SHA384')
.update(message)
.verify(signature, 'base64');
toBuffer(format)
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
new Buffer(key.toString('pem'), 'ascii')
and provided forconvenience only
rfc5951
: (private keys only) returns the encoding of this key as
pkcs8
orrfc5208
: (private keys only) returns the PKCS8 encoding
spki
orrfc5280
: (public keys only) returns the SPKI encoding
toString(format)
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
pkcs8
orrfc5208
: (private keys only) returns the PKCS8 encoding
spki
orrfc5280
: (public keys only) returns the SPKI encoding
toJSON()
Formats this ECDHCrypto
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 ECDHCrypto(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"
// }
example
1. create
const ECDHCrypto = require('ecdh-crypto')
this.randomKey = ECDHCrypto.createECDHCrypto()
var publickey = this.randomKey.asPublicECDHCrypto()
this.publicKey = JSON.stringify(publickey);
2. signature
data = 'SER123456789' + this.publicKey
var signvalue = this.randomKey.doSign(data)
3. verify signagure
var value = this.randomKey.doVerify(data, signvalue)