Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

jsonld-signatures

Package Overview
Dependencies
Maintainers
3
Versions
85
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

jsonld-signatures - npm Package Compare versions

Comparing version 1.0.2 to 1.1.0

tests/bind.js

4

bower.json
{
"name": "jsonld-signatures",
"version": "1.0.2",
"version": "1.1.0",
"moduleType": [

@@ -17,3 +17,3 @@ "amd"

"es6-promise": "~2.0.1",
"jsonld": "~0.4.1",
"jsonld": "~0.4.2",
"forge": "~0.6.34"

@@ -20,0 +20,0 @@ },

@@ -10,3 +10,3 @@ /**

* BSD 3-Clause License
* Copyright (c) 2014 Digital Bazaar, Inc.
* Copyright (c) 2014-2015 Digital Bazaar, Inc.
* All rights reserved.

@@ -55,4 +55,4 @@ *

* @param [options] the options to use:
* [inject] the dependencies to inject, available global defaults will
* be used otherwise.
* [inject] *deprecated*, use `use` API instead; the dependencies to
* inject, available global defaults will be used otherwise.
* [async] async API.

@@ -63,39 +63,8 @@ * [forge] forge API.

* document loader is configured.
* [_] underscore API.
* [disableLocalFraming] true to disable framing of local
* documents based on the given local base URI (default: false).
* [localBaseUri] must be given if disabling local framing.
*/
function wrap(api, options) {
// handle dependency injection
options = options || {};
var inject = options.inject || {};
var async = inject.async || global.async;
var crypto = inject.crypto || global.crypto;
var forge = inject.forge || global.forge;
var jsonld = inject.jsonld || global.jsonldjs;
var _ = inject._ || global._;
var libs = {};
// if dependencies not loaded and using node, load them
if(_nodejs) {
if(!async) {
async = require('async');
}
if(!crypto) {
crypto = require('crypto');
}
if(!forge) {
forge = require('node-forge');
}
if(!jsonld) {
// locally configure jsonld
jsonld = require('jsonld')();
jsonld.useDocumentLoader('node', {secure: true, strictSSL: true});
}
if(!_) {
_ = require('underscore');
}
}
/* API Constants */

@@ -108,2 +77,39 @@

/**
* Allows injectables to be set or retrieved.
*
* @param name the name of the injectable to use (
* eg: `jsonld`, `jsonld-signatures`).
* @param [injectable] the api to set for the injectable, only present for setter,
* omit for getter.
*
* @return the API for `name` if not using this method as a setter, otherwise
* undefined.
*/
api.use = function(name, injectable) {
// setter mode
if(injectable) {
libs[name] = injectable;
return;
}
// getter mode:
// api not set yet, load default
if(!libs[name]) {
// alias `forge` to `node-forge`, `jsonld` to `jsonldjs`
var requireName = (name === 'forge' ? 'node-forge' : name);
var globalName = (name === 'jsonld' ? 'jsonldjs' : name);
libs[name] = global[globalName] || (_nodejs && require(requireName));
if(name === 'jsonld') {
if(_nodejs) {
// locally configure jsonld
libs[name] = libs[name]();
libs[name].useDocumentLoader('node', {secure: true, strictSSL: true});
}
}
}
return libs[name];
};
/**
* Signs a JSON-LD document using a digital signature.

@@ -118,2 +124,4 @@ *

* [nonce] an optional nonce to include in the signature.
* [algorithm] the algorithm to use, eg: 'GraphSignature2012',
* 'LinkedDataSignature2015' (default: 'GraphSignature2012').
* @param callback(err, signedDocument) called once the operation completes.

@@ -131,2 +139,3 @@ */

var nonce = options.nonce || null;
var algorithm = options.algorithm || 'GraphSignature2012';

@@ -149,2 +158,8 @@ if(typeof privateKeyPem !== 'string') {

}
if(['GraphSignature2012', 'LinkedDataSignature2015'].indexOf(
algorithm) === -1) {
return callback(new Error(
'[jsig.sign] options.algorithm must be ' +
'`GraphSignature2012` or `LinkedDataSignature2015`.'));
}

@@ -156,5 +171,15 @@ // create W3C-formatted date

var jsonld = api.use('jsonld');
var async = api.use('async');
async.auto({
normalize: function(callback) {
jsonld.normalize(input, {format: 'application/nquads'}, callback);
var normalizeAlgorithm;
if(algorithm === 'GraphSignature2012') {
normalizeAlgorithm = 'URGNA2012';
} else if(algorithm === 'LinkedDataSignature2015') {
normalizeAlgorithm = 'URDNA2015';
}
jsonld.normalize(
input, {algorithm: normalizeAlgorithm, format: 'application/nquads'},
callback);
},

@@ -165,3 +190,2 @@ sign: ['normalize', function(callback, results) {

var inputJson = '';
try {

@@ -172,3 +196,2 @@ inputJson = JSON.stringify(input, null, 2);

}
return callback(new Error('[jsig.sign] ' +

@@ -182,2 +205,3 @@ 'The data to sign is empty. This error may be caused because ' +

_createSignature(normalized, {
algorithm: algorithm,
privateKeyPem: privateKeyPem,

@@ -193,3 +217,3 @@ date: date,

'@context': api.SECURITY_CONTEXT_URL,
type: 'GraphSignature2012',
type: algorithm,
creator: creator,

@@ -256,3 +280,205 @@ created: date,

options = options || {};
var jsonld = api.use('jsonld');
// TODO: frame before getting signature, not just compact? considerations:
// should the assumption be that the signature is on the top-level object
// and thus framing is unnecessary?
// compact to get signature and types
jsonld.compact(input, api.SECURITY_CONTEXT_URL, function(err, compacted) {
if(err) {
return callback(err);
}
var signature = jsonld.getValues(compacted, 'signature')[0] || null;
if(!signature) {
return callback(new Error('[jsigs.verify] No signature found.'));
}
var algorithm = jsonld.getValues(signature, 'type')[0] || '';
if(['GraphSignature2012', 'LinkedDataSignature2015'].indexOf(
algorithm) === -1) {
return callback(new Error('[jsigs.verify] Unsupported signature type.'));
}
if(algorithm === 'GraphSignature2012') {
return _verifyGraphSignature2012(input, options, callback);
}
if(algorithm === 'LinkedDataSignature2015') {
return _verifyLinkedDataSignature2015(input, options, callback);
}
});
};
/* Helper functions */
/**
* Gets a remote public key.
*
* @param id the ID for the public key.
* @param [options] the options to use:
* [documentLoader(url, callback(err, remoteDoc))] the document loader.
* @param callback(err, key) called once the operation completes.
*/
api.getPublicKey = function(id, options, callback) {
if(typeof options === 'function') {
callback = options;
options = {};
}
options = options || {};
api.getJsonLd(id, options, function(err, key) {
if(err) {
return callback(err);
}
// FIXME: improve validation
if(!('publicKeyPem' in key)) {
return callback(new Error('[jsigs.getPublicKey] ' +
'Could not get public key. Unknown format.'));
}
callback(null, key);
});
};
/**
* Checks to see if the given key is trusted.
*
* @param key the public key to check.
* @param [options] the options to use:
* [publicKeyOwner] the JSON-LD document describing the public key
* owner.
* [checkKeyOwner(owner, key)] a custom method to return whether
* or not the key owner is trusted.
* [documentLoader(url, callback(err, remoteDoc))] the document loader.
* @param callback(err, trusted) called once the operation completes.
*/
api.checkKey = function(key, options, callback) {
if(typeof options === 'function') {
callback = options;
options = {};
}
options = options || {};
var jsonld = api.use('jsonld');
var async = api.use('async');
async.auto({
getOwner: function(callback) {
if(options.publicKeyOwner) {
return callback(null, options.publicKeyOwner);
}
api.getJsonLd(key.owner, options, callback);
},
frameKey: function(callback) {
var frame = {
'@context': api.SECURITY_CONTEXT_URL,
type: 'CryptographicKey'
};
jsonld.frame(key, frame, function(err, framed) {
if(err) {
return callback(err);
}
if(!framed['@graph'][0]) {
return callback(new Error('[jsigs.verify] ' +
'The public key is not a CryptographicKey.'));
}
callback(null, framed['@graph'][0]);
});
},
frameOwner: ['getOwner', function(callback, results) {
var frame = {
'@context': api.SECURITY_CONTEXT_URL,
publicKey: {'@embed': '@never'}
};
jsonld.frame(results.getOwner, frame, function(err, framed) {
if(err) {
return callback(err);
}
callback(null, framed['@graph']);
});
}],
checkOwner: ['frameOwner', 'frameKey', function(callback, results) {
// find specific owner of key
var owner;
var owners = results.frameOwner;
var framedKey = results.frameKey;
for(var i = 0; i < owners.length; ++i) {
if(jsonld.hasValue(owners[i], 'publicKey', framedKey.id)) {
owner = owners[i];
break;
}
}
if(!owner) {
return callback(new Error('[jsigs.verify] ' +
'The public key is not owned by its declared owner.'));
}
if(!options.checkKeyOwner) {
return callback();
}
options.checkKeyOwner(owner, key, options, function(err, trusted) {
if(err) {
return callback(err);
}
if(!trusted) {
return callback(new Error('[jsigs.verify] ' +
'The owner of the public key is not trusted.'));
}
return callback();
});
}]
}, function(err) {
callback(err, !err && true);
});
};
/**
* Retrieves a JSON-LD object over HTTP. To implement caching, override
* this method.
*
* @param url the URL to HTTP GET.
* @param [options] the options to use.
* [documentLoader(url, callback(err, remoteDoc))] the document loader.
* @param callback(err, result) called once the operation completes.
*/
api.getJsonLd = function(url, options, callback) {
if(typeof options === 'function') {
callback = options;
options = {};
}
options = options || {};
var jsonld = api.use('jsonld');
var documentLoader = options.documentLoader || jsonld.documentLoader;
documentLoader(url, function(err, result) {
if(err) {
return callback(err);
}
// ensure result is parsed
if(typeof result.document === 'string') {
try {
result.document = JSON.parse(result.document);
} catch(e) {
return callback(e);
}
}
if(!result.document) {
return callback(new Error(
'[jsigs.getJsonLd] No JSON-LD found at "' + url + '".'));
}
// compact w/context URL from link header
if(result.contextUrl) {
return jsonld.compact(
result.document, result.contextUrl, {expandContext: result.contextUrl},
callback);
}
callback(null, result.document);
});
};
// handle dependency injection
(function() {
var inject = options.inject || {};
for(var name in inject) {
api.use(name, inject[name]);
}
})();
function _verifyGraphSignature2012(input, options, callback) {
var checkTimestamp = (

@@ -262,3 +488,4 @@ 'checkTimestamp' in options ? options.checkTimestamp : false);

'maxTimestampDelta' in options ? options.maxTimestampDelta : (15 * 60));
var jsonld = api.use('jsonld');
var async = api.use('async');
async.auto({

@@ -268,5 +495,2 @@ // FIXME: add support for multiple signatures

// : for signed sigs, need to recurse?
// FIXME: add support for different signature types
// : frame with signatures to get types, then reframe to get
// : correct structure for each type.
frame: function(callback) {

@@ -403,3 +627,4 @@ // frame message to retrieve signature

jsonld.normalize(
result, {format: 'application/nquads'}, function(err, normalized) {
result, {algorithm: 'URGNA2012', format: 'application/nquads'},
function(err, normalized) {
if(err) {

@@ -414,7 +639,7 @@ return callback(err);

var signature = results.normalize.signature;
_verifySignature(results.normalize.data, signature.signatureValue, {
algorithm: 'GraphSignature2012',
publicKeyPem: key.publicKeyPem,
nonce: signature.nonce,
created: signature.created,
date: signature.created,
domain: signature.domain

@@ -426,108 +651,111 @@ }, callback);

});
};
}
/* Helper functions */
/**
* Gets a remote public key.
*
* @param id the ID for the public key.
* @param [options] the options to use:
* [documentLoader(url, callback(err, remoteDoc))] the document loader.
* @param callback(err, key) called once the operation completes.
*/
api.getPublicKey = function(id, options, callback) {
if(typeof options === 'function') {
callback = options;
options = {};
}
options = options || {};
api.getJsonLd(id, options, function(err, key) {
if(err) {
return callback(err);
}
// FIXME: improve validation
if(!('publicKeyPem' in key)) {
return callback(new Error('[jsigs.getPublicKey] ' +
'Could not get public key. Unknown format.'));
}
callback(null, key);
});
};
/**
* Checks to see if the given key is trusted.
*
* @param key the public key to check.
* @param [options] the options to use:
* [publicKeyOwner] the JSON-LD document describing the public key
* owner.
* [checkKeyOwner(owner, key)] a custom method to return whether
* or not the key owner is trusted.
* [documentLoader(url, callback(err, remoteDoc))] the document loader.
* @param callback(err, trusted) called once the operation completes.
*/
api.checkKey = function(key, options, callback) {
if(typeof options === 'function') {
callback = options;
options = {};
}
options = options || {};
function _verifyLinkedDataSignature2015(input, options, callback) {
var checkTimestamp = (
'checkTimestamp' in options ? options.checkTimestamp : false);
var maxTimestampDelta = (
'maxTimestampDelta' in options ? options.maxTimestampDelta : (15 * 60));
var jsonld = api.use('jsonld');
var async = api.use('async');
// TODO: better merge this code with GraphSignature2012 (make more DRY)
async.auto({
getOwner: function(callback) {
if(options.publicKeyOwner) {
return callback(null, options.publicKeyOwner);
}
api.getJsonLd(key.owner, options, callback);
},
frameKey: function(callback) {
var frame = {
// FIXME: add support for multiple signatures
// : for many signers of an object, can just check all sigs
// FIXME: frame to get signature, compacting for now because framing
// requires @graph framing support in jsonld.js
frame: function(callback) {
/* var frame = {
'@context': api.SECURITY_CONTEXT_URL,
type: 'CryptographicKey'
signature: {
type: 'LinkedDataSignature2015',
created: {},
creator: {},
signatureValue: {}
}
};
jsonld.frame(key, frame, function(err, framed) {
if(options.id) {
frame.id = options.id;
}*/
jsonld.compact(input, api.SECURITY_CONTEXT_URL, function(err, framed) {
if(err) {
return callback(err);
}
if(!framed['@graph'][0]) {
var signatures = jsonld.getValues(framed, 'signature');
if(signatures.length > 1) {
return callback(new Error('[jsigs.verify] ' +
'The public key is not a CryptographicKey.'));
'More than one signed graph found.'));
}
callback(null, framed['@graph'][0]);
callback(null, framed);
});
},
frameOwner: ['getOwner', function(callback, results) {
var frame = {
'@context': api.SECURITY_CONTEXT_URL,
publicKey: {'@embed': '@never'}
checkNonce: ['frame', function(callback, results) {
var signature = results.frame.signature;
var cb = function(err, valid) {
if(err) {
return callback(err);
}
if(!valid) {
return callback(new Error('[jsigs.verify] ' +
'The message nonce is invalid.'));
}
callback();
};
jsonld.frame(results.getOwner, frame, function(err, framed) {
if(!options.checkNonce) {
return cb(
null, (signature.nonce === null || signature.nonce === undefined));
}
options.checkNonce(signature.nonce, options, cb);
}],
checkDomain: ['frame', function(callback, results) {
var signature = results.frame.signature;
var cb = function(err, valid) {
if(err) {
return callback(err);
}
callback(null, framed['@graph']);
});
if(!valid) {
return callback(new Error('[jsigs.verify] ' +
'The message domain is invalid.'));
}
callback();
};
if(!options.checkDomain) {
return cb(
null, (signature.domain === null || signature.domain === undefined));
}
options.checkDomain(signature.domain, options, cb);
}],
checkOwner: ['frameOwner', 'frameKey', function(callback, results) {
// find specific owner of key
var owner;
var owners = results.frameOwner;
var framedKey = results.frameKey;
for(var i = 0; i < owners.length; ++i) {
if(jsonld.hasValue(owners[i], 'publicKey', framedKey.id)) {
owner = owners[i];
break;
checkDate: ['frame', function(callback, results) {
if(!checkTimestamp) {
return callback();
}
// ensure signature timestamp within a valid range
var now = new Date().getTime();
var delta = maxTimestampDelta * 1000;
try {
var signature = results.frame.signature;
var created = Date.parse(signature.created);
if(created < (now - delta) || created > (now + delta)) {
throw new Error('[jsigs.verify] ' +
'The message digital signature timestamp is out of range.');
}
} catch(ex) {
return callback(ex);
}
if(!owner) {
callback();
}],
getPublicKey: ['frame', function(callback, results) {
var signature = results.frame.signature;
if(options.publicKey) {
return callback(null, options.publicKey);
}
api.getPublicKey(signature.creator, options, callback);
}],
checkKey: ['getPublicKey', function(callback, results) {
if('revoked' in results.getPublicKey) {
return callback(new Error('[jsigs.verify] ' +
'The public key is not owned by its declared owner.'));
'The message was signed with a key that has been revoked.'));
}
if(!options.checkKeyOwner) {
return callback();
}
options.checkKeyOwner(owner, key, options, function(err, trusted) {
var cb = function(err, trusted) {
if(err) {

@@ -537,57 +765,45 @@ return callback(err);

if(!trusted) {
return callback(new Error('[jsigs.verify] ' +
'The owner of the public key is not trusted.'));
throw new Error('[jsigs.verify] ' +
'The message was not signed with a trusted key.');
}
return callback();
callback();
};
if(options.checkKey) {
return options.checkKey(results.getPublicKey, options, cb);
}
api.checkKey(results.getPublicKey, options, cb);
}],
normalize: [
'checkNonce', 'checkDate', 'checkKey', function(callback, results) {
// remove signature property from object
var result = results.frame;
var signature = result.signature;
delete result.signature;
jsonld.normalize(
result, {algorithm: 'URDNA2015', format: 'application/nquads'},
function(err, normalized) {
if(err) {
return callback(err);
}
callback(null, {data: normalized, signature: signature});
});
}],
verifySignature: ['normalize', function(callback, results) {
var key = results.getPublicKey;
var signature = results.normalize.signature;
_verifySignature(results.normalize.data, signature.signatureValue, {
algorithm: 'LinkedDataSignature2015',
publicKeyPem: key.publicKeyPem,
nonce: signature.nonce,
date: signature.created,
domain: signature.domain
}, callback);
}]
}, function(err) {
callback(err, !err && true);
}, function(err, results) {
callback(err, results.verifySignature);
});
};
}
/**
* Retrieves a JSON-LD object over HTTP. To implement caching, override
* this method.
*
* @param url the URL to HTTP GET.
* @param [options] the options to use.
* [documentLoader(url, callback(err, remoteDoc))] the document loader.
* @param callback(err, result) called once the operation completes.
*/
api.getJsonLd = function(url, options, callback) {
if(typeof options === 'function') {
callback = options;
options = {};
}
options = options || {};
var documentLoader = options.documentLoader || jsonld.documentLoader;
documentLoader(url, function(err, result) {
if(err) {
return callback(err);
}
// ensure result is parsed
if(typeof result.document === 'string') {
try {
result.document = JSON.parse(result.document);
} catch(e) {
return callback(e);
}
}
if(!result.document) {
return callback(new Error(
'[jsigs.getJsonLd] No JSON-LD found at "' + url + '".'));
}
// compact w/context URL from link header
if(result.contextUrl) {
return jsonld.compact(
result.document, result.contextUrl, {expandContext: result.contextUrl},
callback);
}
callback(null, result.document);
});
};
/**
* Implements the node.js/browser-specific code for creating a digital

@@ -597,3 +813,4 @@ * signature.

* @param input the data to sign.
* @param [options] options to use:
* @param options options to use:
* algorithm 'GraphSignature2012' or 'LinkedDataSignature2015'.
* privateKeyPem A PEM-encoded private key.

@@ -605,40 +822,23 @@ * [date] an optional date to override the signature date with.

*/
var _createSignature = null;
if(_nodejs) {
_createSignature = function(input, options, callback) {
// generate base64-encoded signature
var signer = crypto.createSign('RSA-SHA256');
if(options.nonce !== null) {
signer.update(options.nonce);
}
signer.update(options.date);
var _createSignature = (function() {
if(_nodejs) {
return function(input, options, callback) {
var crypto = api.use('crypto');
var signer = crypto.createSign('RSA-SHA256');
signer.update(_getDataToHash(input, options), 'utf8');
var signature = signer.sign(options.privateKeyPem, 'base64');
callback(null, signature);
};
} else if(_browser) {
return function(input, options, callback) {
var forge = api.use('forge');
var privateKey = forge.pki.privateKeyFromPem(options.privateKeyPem);
var md = forge.md.sha256.create();
md.update(_getDataToHash(input, options), 'utf8');
var signature = forge.util.encode64(privateKey.sign(md));
callback(null, signature);
};
}
})();
signer.update(input);
if(options.domain !== null) {
signer.update('@' + options.domain);
}
var signature = signer.sign(options.privateKeyPem, 'base64');
callback(null, signature);
};
} else if(_browser) {
_createSignature = function(input, options, callback) {
// convert a PEM-formatted private key to a Forge private key
var privateKey = forge.pki.privateKeyFromPem(options.privateKeyPem);
var md = forge.md.sha256.create();
if(options.nonce !== null) {
md.update(options.nonce);
}
md.update(options.date);
md.update(input);
if(options.domain !== null) {
md.update('@' + options.domain);
}
var signature = forge.util.encode64(privateKey.sign(md));
callback(null, signature);
};
}
/**

@@ -650,3 +850,4 @@ * Implements the node.js/browser-specific code for creating a digital

* @param signature the base-64 encoded signature on the data.
* @param [options] options to use:
* @param options options to use:
* algorithm 'GraphSignature2012' or 'LinkedDataSignature2015'.
* publicKeyPem A PEM-encoded public key.

@@ -658,46 +859,59 @@ * [date] an optional date to override the signature date with.

*/
var _verifySignature = null;
if(_nodejs) {
_verifySignature = function(input, signature, options, callback) {
var verifier = crypto.createVerify('RSA-SHA256');
if(options.nonce) {
verifier.update(options.nonce);
}
verifier.update(options.created);
verifier.update(input);
if(options.domain) {
verifier.update('@' + options.domain);
}
var _verifySignature = (function() {
if(_nodejs) {
return function(input, signature, options, callback) {
var crypto = api.use('crypto');
var verifier = crypto.createVerify('RSA-SHA256');
verifier.update(_getDataToHash(input, options), 'utf8');
var verified = verifier.verify(options.publicKeyPem, signature, 'base64');
if(!verified) {
return callback(new Error('[jsigs.verify] ' +
'The digital signature on the message is invalid.'));
}
callback(null, verified);
};
} else if(_browser) {
return function(input, signature, options, callback) {
var forge = api.use('forge');
var publicKey = forge.pki.publicKeyFromPem(options.publicKeyPem);
var md = forge.md.sha256.create();
md.update(_getDataToHash(input, options), 'utf8');
var verified = publicKey.verify(
md.digest().bytes(), forge.util.decode64(signature));
if(!verified) {
return callback(new Error('[jsigs.verify] ' +
'The digital signature on the message is invalid.'));
}
callback(null, verified);
};
}
})();
var verified = verifier.verify(options.publicKeyPem, signature, 'base64');
if(!verified) {
return callback(new Error('[jsigs.verify] ' +
'The digital signature on the message is invalid.'));
function _getDataToHash(input, options) {
var toHash = '';
if(options.algorithm === 'GraphSignature2012') {
if(options.nonce !== null && options.nonce !== undefined) {
toHash += options.nonce;
}
callback(null, verified);
};
} else if(_browser) {
_verifySignature = function(input, signature, options, callback) {
var publicKey = forge.pki.publicKeyFromPem(options.publicKeyPem);
var md = forge.md.sha256.create();
if(options.nonce !== undefined) {
md.update(options.nonce);
toHash += options.date;
toHash += input;
if(options.domain !== null && options.domain !== undefined) {
toHash += '@' + options.domain;
}
md.update(options.created);
md.update(input);
if(options.domain !== undefined) {
md.update('@' + options.domain);
} else if(options.algorithm === 'LinkedDataSignature2015') {
// headers are lexicographical order
var headers = {
'http://purl.org/dc/elements/1.1/created': options.date,
'https://w3id.org/security#domain': options.domain,
'https://w3id.org/security#nonce': options.nonce
};
for(var key in headers) {
var value = headers[key];
if(value !== null && value !== undefined) {
toHash = key + ':' + value + '\n';
}
}
var verified = publicKey.verify(
md.digest().bytes(), forge.util.decode64(signature));
if(!verified) {
return callback(new Error('[jsigs.verify] ' +
'The digital signature on the message is invalid.'));
}
callback(null, verified);
};
toHash += input;
}
return toHash;
}

@@ -773,2 +987,3 @@

var slice = Array.prototype.slice;
var jsonld = api.use('jsonld');
var promisify = jsonld.promisify;

@@ -812,8 +1027,5 @@

// used to generate a new verifier API instance
var factory = function(inject) {
return wrap(function() {return factory();}, inject);
var factory = function(options) {
return wrap(function() {return factory();}, options);
};
// TODO: remove automatic wrapping as it forces certain hard-coded dependencies
// that may not actually be required (as they are instead provided via
// dependency injection)... this may require a version bump
wrap(factory);

@@ -820,0 +1032,0 @@

{
"name": "jsonld-signatures",
"version": "1.0.2",
"version": "1.1.0",
"description": "An implementation of the Linked Data Signatures specification for JSON-LD in node.js.",

@@ -33,8 +33,3 @@ "homepage": "http://github.com/digitalbazaar/jsonld-signatures",

},
"licenses": [
{
"type": "BSD",
"url": "https://github.com/digitalbazaar/jsonld-signatures/raw/master/LICENSE"
}
],
"license": "BSD-3-Clause",
"main": "lib/jsonld-signatures.js",

@@ -45,3 +40,3 @@ "dependencies": {

"es6-promise": "~2.0.1",
"jsonld": "~0.4.1",
"jsonld": "~0.4.2",
"node-forge": "~0.6.18",

@@ -48,0 +43,0 @@ "underscore": "~1.7.0"

@@ -28,2 +28,3 @@ /**

var system = require('system');
require('./bind');
require('./setImmediate');

@@ -113,3 +114,3 @@ var _jsdir = system.env.JSDIR || 'lib';

describe('signing and verify w/o security context', function() {
describe('signing and verify Graph2012 w/o security context', function() {
// the test document that will be signed

@@ -131,2 +132,3 @@ var testDocument = {

jsigs.sign(testDocument, {
algorithm: 'GraphSignature2012',
privateKeyPem: testPrivateKeyPem,

@@ -161,4 +163,51 @@ creator: testPublicKeyUrl

describe('signing and verify w/security context', function() {
describe('signing and verify Graph2015 w/o security context', function() {
// the test document that will be signed
var testDocument = {
'@context': {
schema: 'http://schema.org/',
name: 'schema:name',
homepage: 'schema:url',
image: 'schema:image'
},
name: 'Manu Sporny',
homepage: 'https://manu.sporny.org/',
image: 'https://manu.sporny.org/images/manu.png'
};
var testDocumentSigned = {};
it('should successfully sign a local document', function(done) {
jsigs.sign(testDocument, {
algorithm: 'LinkedDataSignature2015',
privateKeyPem: testPrivateKeyPem,
creator: testPublicKeyUrl
}, function(err, signedDocument) {
assert.ifError(err);
assert.notEqual(
signedDocument['https://w3id.org/security#signature'], undefined,
'signature was not created');
assert.equal(
signedDocument['https://w3id.org/security#signature']
['http://purl.org/dc/terms/creator']['@id'], testPublicKeyUrl,
'creator key for signature is wrong');
testDocumentSigned = signedDocument;
done();
});
});
it('should successfully verify a local signed document', function(done) {
jsigs.verify(testDocumentSigned, {
publicKey: testPublicKey,
publicKeyOwner: testPublicKeyOwner
}, function(err, verified) {
assert.ifError(err);
assert.equal(verified, true, 'signature verification failed');
done();
});
});
});
describe('signing and verify GraphSignature2012 w/security context', function() {
// the test document that will be signed

@@ -180,2 +229,3 @@ var testDocument = {

jsigs.sign(testDocument, {
algorithm: 'GraphSignature2012',
privateKeyPem: testPrivateKeyPem,

@@ -206,2 +256,47 @@ creator: testPublicKeyUrl

});
describe('signing and verify LinkedDataSignature2015 w/security context', function() {
// the test document that will be signed
var testDocument = {
'@context': [{
schema: 'http://schema.org/',
name: 'schema:name',
homepage: 'schema:url',
image: 'schema:image'
}, jsigs.SECURITY_CONTEXT_URL],
name: 'Manu Sporny',
homepage: 'https://manu.sporny.org/',
image: 'https://manu.sporny.org/images/manu.png'
};
var testDocumentSigned = {};
it('should successfully sign a local document', function(done) {
jsigs.sign(testDocument, {
algorithm: 'LinkedDataSignature2015',
privateKeyPem: testPrivateKeyPem,
creator: testPublicKeyUrl
}, function(err, signedDocument) {
assert.ifError(err);
assert.notEqual(signedDocument.signature, undefined,
'signature was not created');
assert.equal(signedDocument.signature.creator, testPublicKeyUrl,
'creator key for signature is wrong');
testDocumentSigned = signedDocument;
done();
});
});
it('should successfully verify a local signed document', function(done) {
jsigs.verify(testDocumentSigned, {
publicKey: testPublicKey,
publicKeyOwner: testPublicKeyOwner
}, function(err, verified) {
assert.ifError(err);
assert.equal(verified, true, 'signature verification failed');
done();
});
});
});
});

@@ -227,2 +322,3 @@

"GraphSignature2012": "sec:GraphSignature2012",
"LinkedDataSignature2015": "sec:LinkedDataSignature2015",
"CryptographicKey": "sec:Key",

@@ -229,0 +325,0 @@

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc