Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 16 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,32 +20,36 @@ A JavaScript implementation of Secure Content Resource (SCR) for current web bro
To install the latest from [NPM](https://npmjs.com/):

```
npm install node-scr
{@lang bash}
npm install node-scr
```

Or to install a specific release:

```
npm install [email protected]
{@lang bash}
npm install [email protected]
```

Alternatively, the latest unpublished code can be installed directly from the repository:

```
npm install git+ssh://[email protected]:cisco/node-scr.git
{@lang bash}
npm install git+ssh://[email protected]:cisco/node-scr.git
```

## Basics ##

Require the library as normal:

```
{@lang javascript}
var SCR = require("node-scr");
```

This library uses [Promises](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) for most operations.

This library supports [Browserify](http://browserify.org/). To use in a web browser, `require('node-kms')` and bundle with the rest of your app.
This library supports [Browserify](http://browserify.org/). To use in a web browser, `require('node-scr')` and bundle with the rest of your app.

The content to be encrypted or returned from being decrypted are [Buffer](https://nodejs.org/api/buffer.html) objects.

Expand All @@ -54,6 +58,7 @@ The content to be encrypted or returned from being decrypted are [Buffer](https:
To create an empty SCR:

```
{@lang javascript}
var scrObject;
SCR.create().
then(function(result) {
Expand Down Expand Up @@ -81,6 +86,7 @@ The "loc" member is set by the API user, and the "tag" member is set by `scrObje
To encrypt content:

```
{@lang javascript}
// {input} is one of:
// - a node.js Buffer
// - an ArrayBuffer
Expand All @@ -98,6 +104,7 @@ The result from `encrypt()`'s resolved Promise can be passed directly to a WebSo
To decrypt content:

```
{@lang javascript}
// *NOTE:* {scrObject} has the correct "tag" for the (encrypted) content
scrObject.decrypt(output).
then(function(input) {
Expand All @@ -113,6 +120,7 @@ Encrypted JWEs are appropriate to be shared with recipients.
To export the SCR as a JWE:

```
{@lang javascript}
var jwe;
// {key} is a JWK from 'node-jose', or the JSON representation of a JWK
scrObject.toJWE(key).
Expand All @@ -125,6 +133,7 @@ scrObject.toJWE(key).
To import the SCR from a JWE:

```
{@lang javascript}
var scrObject;
// {key} is a JWK from 'node-jose', or the JSON representation of a JWK
// {jwe} is a JWE using any of the serializations (Compact, JSON Flattened, JSON General)
Expand Down Expand Up @@ -160,6 +169,7 @@ The "loc" and "tag" members are optional:
A complete example of an SCR as JSON:

```
{@lang javascript}
{
"enc": "A256GCM",
"key": "Ce3pe4stGd3tvZdSR3ekIoNjF3Q3V6R0oMN4SSGKbyI",
Expand All @@ -173,12 +183,14 @@ A complete example of an SCR as JSON:
To export an SCR to a JSON object:

```
{@lang javascript}
var output = scrObject.toJSON();
```

To import an SCR from a JSON object:

```
{@lang javascript}
var scrObject;
// {input} is a JSON representation
SCR.create(input).
Expand Down
17 changes: 11 additions & 6 deletions gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ var browserify = require("browserify"),
karma = require("karma"),
merge = require("lodash.merge"),
mocha = require("gulp-mocha"),
runSequence = require("run-sequence");
runSequence = require("run-sequence"),
shell = require("gulp-shell");

// ### 'CONSTANTS' ###
var SOURCES = ["./lib/**/*.js", "!(./lib/old/**/*.js)"],
Expand Down Expand Up @@ -80,12 +81,16 @@ gulp.task("clean:dist", function() {

// ### DOCUMENTATION TASKS ###
gulp.task("doc:readme", function() {
gulp.src("./README.md").
pipe(doctoc({
title: "<a name='toc'>"
})).
pipe(gulp.dest("./"));
return gulp.src("./README.md").
pipe(doctoc({
title: "<a name='toc'>"
})).
pipe(gulp.dest("./"));
});
gulp.task("doc:js", shell.task([
"./node_modules/.bin/jsdoc --configure ./jsdoc.json"
]));
gulp.task("doc", ["doc:readme", "doc:js"]);

// ### NODEJS TASKS ###
function doTestsNodejs() {
Expand Down
28 changes: 28 additions & 0 deletions jsdoc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"source": {
"include": [ "README.md", "lib/index.js"]
},
"plugins": [
"plugins/markdown"
],
"templates": {
"default": {
"outputSourceFiles": false
},
"colapseSymbols": false,
"copyright": "Copyright © 2015 Cisco Systems, Inc.",
"monospaceLinks": true,
"outputSourceFiles": false,
"syntaxTheme": "dark",
"theme": "simplex"
},
"markdown": {
"parser": "gfm",
"hardwrap": true
},
"opts": {
"destination": "./dist/docs",
"encoding": "utf8",
"template": "./node_modules/ink-docstrap/template"
}
}
130 changes: 128 additions & 2 deletions lib/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/**!
/*!
* lib/index.js -- SCR Implementation
*
* Copyright (c) 2015 Cisco Systems, Inc. See LICENSE file.
Expand All @@ -8,34 +8,83 @@
var clone = require("lodash.clone"),
jose = require("node-jose");

/**
* @class SCRObject
* @classdesc
* Representation of a Secure Content Resource (SCR).
*
* Instances of this class are not created directly, but instead through
* {@link SCR.create}, {@link SCR.fromJSON}, or {@link SCR.fromJWE}.
*/

/**
* @desc
* Creates a new SCR, optionally with the given configuration.
*
* `cfg`, if provided, is expected to match the output from
* {@link SCRObject#toJSON}.
*
* @param {Object} [cfg] The configuration object
* @private
*/
function SCRObject(cfg) {
cfg.loc = cfg.loc || undefined;
cfg.tag = cfg.tag || undefined;

/**
* The algorithm used to encrypt the content.
*
* @member {String} enc
* @memberof SCRObject#
*/
Object.defineProperty(this, "enc", {
get: function() {
return cfg.enc;
},
enumerable: true
});
/**
* The key used to encrypt the content.
*
* @member {jose.JWK.Key} key
* @memberof SCRObject#
*/
Object.defineProperty(this, "key", {
get: function() {
return cfg.key;
},
enumerable: true
});
/**
* The initialization vector used to encrypt the content.
*
* @member {Buffer} iv
* @memberof SCRObject#
*/
Object.defineProperty(this, "iv", {
get: function() {
return cfg.iv;
},
enumerable: true
});
/**
* The additional authenticated data used to encrypt the content.
*
* @member {String} aad
* @memberof SCRObject#
*/
Object.defineProperty(this, "aad", {
get: function() {
return cfg.aad;
},
enumerable: true
});
/**
* The location where encrypted content can be found.
*
* @member {String} loc
* @memberof SCRObject#
*/
Object.defineProperty(this, "loc", {
get: function() {
return cfg.loc;
Expand All @@ -45,13 +94,26 @@ function SCRObject(cfg) {
},
enumerable: true
});
/**
* The authentication tag from encrypting content.
*
* @member {Buffer} tag
* @memberof SCRObject#
*/
Object.defineProperty(this, "tag", {
get: function() {
return cfg.tag;
},
enumerable: true
});

/**
* Generates a JSON representation of this SCR.
*
* @function toJSON
* @memberof SCRObject#
* @returns {Object} The JSON representation of this SCR
*/
Object.defineProperty(this, "toJSON", {
value: function() {
var key = cfg.key.get("k", true);
Expand All @@ -71,6 +133,14 @@ function SCRObject(cfg) {
return data;
}
});
/**
* Encrypts the JSON representation of this SCR.
*
* @function toJWE
* @memberof SCRObject#
* @param {jose.JWK} jwk The key to encrypt this SCR with
* @returns {Promise} A Promise for the encrypted SCR (when fulfilled)
*/
Object.defineProperty(this, "toJWE", {
value: function(jwk) {
var self = this,
Expand Down Expand Up @@ -99,6 +169,19 @@ function SCRObject(cfg) {
}
});

/**
* Encrypts the given content. Content is encrypted using the
* {@link SCRObject#key}, {@link SCRObject#iv}, and {@link SCRObject#aad}.
*
* When the returned Promise is fulfilled, any resolved callbacks are passed
* the encrypted content as a Buffer, and {@link SCRObject#tag} is modified to
* contain the encrypted content's authentication tag.
*
* @function encrypt
* @memberof SCRObject#
* @param {Buffer|ArrayBuffer|ArrayBufferView} pdata The content to encrypt.
* @returns {Promise} A Promise for the encrypted content (when fulfilled)
*/
Object.defineProperty(this, "encrypt", {
value: function(pdata) {
var props = {
Expand All @@ -117,6 +200,18 @@ function SCRObject(cfg) {
});
}
});
/**
* Decrypts the given content. Content is decrypted using the {@link SCRObject#key},
* {@link SCRObject#iv}, {@link SCRObject#aad}, and {@link SCRObject#tag}.
*
* When the returned Promise is fulfilled, any resolved callbacks are passed
* the decrypted content as a Buffer.
*
* @function decrypt
* @memberof SCRObject#
* @param {Buffer|ArrayBuffer|ArrayBufferView} pdata The content to encrypt.
* @returns {Promise} A Promise for the encrypted content (when fulfilled)
*/
Object.defineProperty(this, "decrypt", {
value: function(cdata) {
var props = {
Expand All @@ -135,10 +230,22 @@ function SCRObject(cfg) {
});
}

/**
* Entry point namespace Secure Content Resources.
*
* @namespace SCR
*/
var SCR = {
/**
* Creates a new {@link SCRObject} initialized with a content encryption key.
*
* The returned promise, when fulfilled, returns the new SCR instance to
* all resolve callbacks.
*
* @returns {Promise} A promise for a new SCR.
*/
create: function() {
// TODO: make this more configurable
// TODO: abstract away forge??
var iv = jose.util.randomBytes(12);
var aad = new Date().toISOString();

Expand All @@ -155,6 +262,16 @@ var SCR = {

return promise;
},
/**
* Decrypts an encrypted SCR into a {@link SCRObject} instance.
*
* The returned promise, when fulfilled, returns the decrypted SCR to all
* resolve callbacks.
*
* @param {jose.JWK.Key} jwk The key to decrypt the SCR with
* @param {String | Object} jwe The encrypted SCR to decrypt
* @returns {Promise} A promise for the decrypted SCR
*/
fromJWE: function(jwk, jwe) {
var promise;
promise = jose.JWK.asKey(jwk);
Expand All @@ -169,6 +286,15 @@ var SCR = {

return promise;
},
/**
* Parses the given JSON representation into a {@link SCRObject} instance.
*
* The returned promise, when fulfilled, returns the parsed SCR
* to all resolve callbacks.
*
* @param {Object} json The JSON representation of a SCR
* @returns {Promise} A promise for the parsed SCR instance
*/
fromJSON: function(json) {
// create a copy to mitigate tampering
var cfg = clone(json);
Expand Down
Loading