A JavaScript implementation of Key Management Service (KMS) for current web browsers and node.js-based servers. The KMS API is described in [draft-abiggs-saag-key-management-service-02].
To install the latest from NPM:
npm install node-kms
Or to install a specific release:
npm install [email protected]
Alternatively, the latest unpublished code can be installed directly from the repository:
npm install git+ssh://[email protected]:cisco/node-kms.git
Require the library as normal:
var KMS = require('node-kms');
This library uses Promises for many operations.
This library supports Browserify. To use in a web browser, require('node-kms')
and bundle with the rest of your app.
A KMS KeyObject wraps a JSON Web Key (JWK) to provide more semantics: a URI to locate it; the creating user and client; the date/time of when a key is created, bound, and/or expires; and the owning resource (once bound).
To create an empty KeyObject:
var keyobj = new KMS.KeyObject();
None of the KMS.KeyObject properties are set.
Alternatively, to create a KeyObject from a JSON or POJO representation:
// {input} is one of:
// * a JSON object (where date/times are RFC3339-encoded Strings)
// * a POJO (where date/times are Date objects)
var keyobj = new.KeyObject(input);
NOTE: The JSON representation includes all properties for a KeyObject, including the full JWK (if present). This can expose secret key material if not carefully handled; do not save to durable storage without protecting it (e.g., encrypting to a JWE).
To import a KeyObject from a JSON object:
// {input} is one of:
// * a JSON object (where date/times are RFC3339-encoded Strings)
// * a POJO (where date/times are Date objects)
// * an existing KeyObject instance
keyobj = KMS.fromObject(input);
In the case where input
is already a KeyObject, it is returned as-is.
To export a KeyObject to a JSON object:
var output = keyobj.toJSON();
To convert the jwk
property of a KeyObject to a node-jose
Key (to use for encryption or signatures):
var jwk;
keyobj.asKey().
then(function(result) {
// {result} is a jose.JWK.Key
jwk = result;
});
If jwk
is not set on the KeyObject, the returned Promise is rejected.
The KMS.Context holds onto information necessary to wrap Requests and unwrap Responses.
To create an empty Context:
var kmsCtx = new KMS.Context();
None of the Context properties are set.
To finish initializing the Context, set the clientInfo
and serverInfo
properties:
// {clientId} is a String containing an identifier for the client or session
// {userId} is a String containing the user's identifier
// {oauth2token} is a String containing an OAuth2 Bearer token
kmsCtx.clientInfo = {
clientId: clientId,
credential: {
userId: userId,
bearer: oauth2token
}
};
// {serverPublicKey} is a JWK JSON object
kmsCtx.serverInfo = {
key: serverPublicKey
};
To create a KeyObject representing the local ECDH key:
kmsCtx.createECDHKey().
then(function(result) {
// {result} is a KMS.KeyObject wrapping a "EC" JWK
kmsCtx.ephemeralKey = result;
})
To derive an ephemeral shared key -- such as the result of the ECDHE handshake:
// {remoteECDH} is a KMS.KeyObject wrapping a "EC" JWK
kmsCrx.deriveEphemeralKey(remoteECDH).
then(function(result) {
// {result} is a KMS.KeyObject wrapping a "oct" JWK
kmsCtx.ephemeralKey = result;
});
The KMS.Request embodies a single request from a client to the KMS.
A Request instance has the following (read/write) properties:
body
-- the full (plaintext) JSON to be sent to the KMSrequestId
-- the unique id for this requesturi
-- the URI of the request (e.g., "/ecdhe/", "/resources", etc.)method
-- the method (verb) for the request (e.g., "create", "retrieve", etc.)wrapped
-- the wrapped (encrypted)body
When a new body
is set, the previous requestId
, method
, and uri
are remembered, overwriting any new values that might have been in the provided JSON.
To create an empty request:
var request = new KMS.Request();
To create a request starting with a constructed body:
// {input} is a JSON object representing the request
var request = new KMS.Request(input);
To wrap (encrypt) the Request into a JWE for transmitting to a KMS server, using an ephemeral shared key:
var output;
request.wrap(kmsCtx).
then(function(result) {
// {result} is a String of the JWE in the Compact Serialization
// request.wrapped is also set to {result}
output = result;
});
The KMS.Response embodies a single response to a client from the KMS.
A Response instance has the following (read/write) properties:
body
-- the full (plaintext) JSON received from the KMSrequestId
-- the id for the corresponding requeststatus
-- the status code of the responsereason
-- the string reason (if any)wrapped
-- the protected (encrypted or signed)body
To create an empty KMS.Response:
var response = new KMS.Response();
To creat a KMS.Response with a received wrapped body:
// {input} is a String of the JWE (or JWS) using the Compact Serialization
var response = new KMS.Response(input);
To unwrap a response into the plaintext body:
var input;
response.unwrap(kmsCtx).
then(function(result) {
// {result} is the plaintext JSON object
// response.body is also set to {result}
input = result;
});