Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reorganize suites for external signing/verification #45

Merged
merged 84 commits into from Jan 1, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
84 commits
Select commit Hold shift + click to select a range
fa4741e
Add proofPurpose checking.
cwebber Oct 3, 2018
a058c38
Update tests to use new proofPurpose option.
cwebber Oct 3, 2018
620917e
Rename `ppOptions` to `proofPurposeOptions`.
gannan08 Nov 1, 2018
f08d6f9
Use the expanded input for compaction.
gannan08 Nov 1, 2018
14ba012
Refactor proof purpose.
gannan08 Nov 1, 2018
ac30f43
Add CredentialIssuance to proofPurposes.
gannan08 Nov 2, 2018
e8527a8
Expose ProofPurpose class and fix linting errors.
gannan08 Nov 9, 2018
d52ca67
Update linting rules.
mattcollier Nov 13, 2018
41ad3e1
Fix style.
mattcollier Nov 13, 2018
fb8fe74
Simplify async map syntax.
mattcollier Nov 13, 2018
8040c3a
Fix style.
mattcollier Nov 13, 2018
9fa9ddf
Remove fixme.
mattcollier Nov 13, 2018
9df9c19
Update sign/verify parameters.
mattcollier Nov 14, 2018
9b9ffe3
Use `Buffer.from` to instantiate buffers.
mattcollier Nov 14, 2018
61d6a7e
Remove CredentialIssuance.
mattcollier Nov 14, 2018
61f3468
Enable node6 support in travis CI.
mattcollier Nov 14, 2018
908ad73
Refactor proofPurpose verification.
mattcollier Nov 14, 2018
4d8384c
Remove TODO.
mattcollier Nov 28, 2018
3e14fbc
Use injector API for proofPurposes.
mattcollier Nov 28, 2018
b65079a
Update context.
gannan08 Nov 28, 2018
d6b1964
Integrate proof purpose.
gannan08 Nov 28, 2018
01ec53d
Remove debugging.
gannan08 Nov 29, 2018
a9c7736
Add check for supported proof purpose.
gannan08 Nov 30, 2018
17bd967
Remove jsonld expansion step.
gannan08 Nov 30, 2018
f6b26e3
Update context.
gannan08 Nov 30, 2018
d056ede
Add support for object spread operator.
gannan08 Dec 3, 2018
a1d9ebd
Create a proper binary string in browser mode.
gannan08 Dec 3, 2018
7e4e076
Add test to verify signature for Ed25519.
gannan08 Dec 3, 2018
2cfaac8
Add note on the non-deterministic nature of some signatures.
gannan08 Dec 3, 2018
a31867b
Prefer spread operator.
gannan08 Dec 4, 2018
1614348
Add test for unknown proof purpose.
gannan08 Dec 4, 2018
c103b35
Make supported proof purpose check more robust.
gannan08 Dec 4, 2018
f692528
Update Injector.js API.
gannan08 Dec 4, 2018
dbe5e9b
Pass document loader to proof purpose handler.
gannan08 Dec 5, 2018
6ffaf11
Move proof purpose validation option to the beginning of the function.
gannan08 Dec 5, 2018
2c012d9
Pass in the purpose parameter.
gannan08 Dec 5, 2018
4de3c89
Throw error if proof purpose not found in proof.
gannan08 Dec 5, 2018
0358b3b
Register jsigs with its own injector.
gannan08 Dec 7, 2018
3b35f5e
Add `capabilityChain` term to security-v2 cached context.
dlongley Dec 11, 2018
c44d226
Pass `input` and `documentLoader` and use object spread.
dlongley Dec 11, 2018
7469543
Verify proof node before verifying proof purpose.
dlongley Dec 11, 2018
cb2076c
Verify signature before checking key trust (which often hits network).
dlongley Dec 11, 2018
aed60d4
Pass `publicKey` and `keyOptions` to proof purpose.
dlongley Dec 12, 2018
cdc6d82
Destructure valid/error from proof purpose handler.
dlongley Dec 13, 2018
0b0c558
Implement signer API.
mattcollier Nov 15, 2018
8ec702a
Add docstring/params to sign() related functions.
dmitrizagidulin Dec 5, 2018
f132558
Refactor signing api, support injected custom suite
dmitrizagidulin Dec 13, 2018
ad2aaf1
Move suites and utilities to a separate module.
dlongley Dec 19, 2018
7131f98
Move environment checks into a separate module.
dlongley Dec 19, 2018
1c94a89
Reorganize suites and rework APIs and internals.
dlongley Dec 19, 2018
04e0364
Use alias for jsonld that loads prebuilt package.
dlongley Dec 23, 2018
e638393
Update test suite and fix related bugs.
dlongley Dec 24, 2018
764b088
Enable common tests; rename `ProofPurposeHandler`.
dlongley Dec 26, 2018
edfbb11
Implement `ControllerProofPurpose` and `PublicKeyProofPurpose`.
dlongley Dec 26, 2018
1497b84
Add TODO.
dlongley Dec 26, 2018
7057e78
Remove unused code; general clean up.
dlongley Dec 26, 2018
e129d66
Reorganize mock data.
dlongley Dec 26, 2018
497621e
Add CustomSuite test and reorganize exposed suites/purposes.
dlongley Dec 27, 2018
ca86e51
Remove old boilerplate and callback API.
dlongley Dec 27, 2018
d06a4d6
Add tests for `PublicKeyProofPurpose`.
dlongley Dec 27, 2018
1ac3387
Pass karma tests.
dlongley Dec 27, 2018
be461dc
Add processing flag, authentication proof purpose, and clean up API.
dlongley Dec 27, 2018
aa6d80d
Rename `assumeSecurityContext` to `proofTermDefined`.
dlongley Dec 27, 2018
6d99ebc
Test `proofTermDefined` flag.
dlongley Dec 27, 2018
2127226
Default `proofTermDefined` to `false` and update CHANGELOG.
dlongley Dec 27, 2018
0872ef8
Move `LDKeyPair` and update README.
dlongley Dec 27, 2018
597a44b
Fixup README.
dlongley Dec 27, 2018
bdef224
Auto-populate verificationMethod/creator if not specified.
dlongley Dec 27, 2018
168edb7
Return `controller` in `validate` result.
dlongley Dec 28, 2018
dad8549
Remove unused construction parameters; move date check into ProofPurp…
dlongley Dec 28, 2018
9e73c28
Reimplement `proofTermDefined` as `compactProof`.
dlongley Dec 30, 2018
815b84e
Explicitly test compactProof true/false.
dlongley Dec 31, 2018
4c6a110
Add some docs.
dlongley Dec 31, 2018
815dfc9
Add docs to ProofPurpose base class.
dlongley Dec 31, 2018
7c65dcf
Allow `verificationMethod` to be used instead of `creator`.
dlongley Dec 31, 2018
bfc1266
Fix `strictDocumentLoader` name.
dlongley Jan 1, 2019
7fca973
Do not use `expansionMap` when retrieving keys/controllers.
dlongley Jan 1, 2019
8b69858
Compact input to security context for consistency.
dlongley Jan 1, 2019
5197451
Expose document loader helpers.
dlongley Jan 1, 2019
c3a0ad3
Use Date constructor to convert date.
dlongley Jan 1, 2019
3cf45e7
Validate `date`.
dlongley Jan 1, 2019
da75d06
Handle `NaN` case for `proof.created`.
dlongley Jan 1, 2019
94dd0cf
Simplify w3c date creation.
dlongley Jan 1, 2019
2840b09
Do not modify suite state during verification.
dlongley Jan 1, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintrc
@@ -1,5 +1,6 @@
{
"env": {
"amd": true,
"browser": true
},
"rules": {
Expand Down
3 changes: 2 additions & 1 deletion .travis.yml
Expand Up @@ -19,7 +19,8 @@ script:
# only run karma tests for one node version
matrix:
include:
- node_js: "6"
- name: "Browser Unit Tests"
node_js: "6"
env: BUNDLER=webpack
# - node_js: "6"
# env: BUNDLER=browserify
Expand Down
22 changes: 22 additions & 0 deletions CHANGELOG.md
@@ -1,5 +1,27 @@
# jsonld-signatures ChangeLog

## 3.0.0 - TBD

### Added
- Add `compactProof` flag that can be set to `false` to enable skipping
compaction of proof(s) when it is known that the input document's (for `sign`
or `verify`) JSON-LD `@context` defines all applicable proof terms using the
same definitions as the JSON-LD `@context` used internally by the library
(i.e. the JSON-LD `@context` defined by `constants.SECURITY_CONTEXT_URL`).
This flag should only be set to `false` by advanced users that have ensured
their software systems have strictly validated the input to ensure that it
is safe and cannot be misinterpreted. If these guarantees can be met, then
setting this flag to `false` may be a useful optimization consideration.

### Changed
- **BREAKING**: `sign` and `verify` APIs require suites and proof purpose
instances to be passed.

### Removed
- **BREAKING**: Removed API `wrap` and injector support.
- **BREAKING**: callback-based API is no longer supported.
- **BREAKING**: Removed exposed utility/helper functions.

## 2.3.1 - 2018-09-05

### Changed
Expand Down
3 changes: 2 additions & 1 deletion LICENSE
@@ -1,4 +1,5 @@
Copyright (c) 2014-2017, Digital Bazaar, Inc.
BSD 3-Clause License
Copyright (c) 2010-2018 Digital Bazaar, Inc.
All rights reserved.

Redistribution and use in source and binary forms, with or without
Expand Down
179 changes: 133 additions & 46 deletions README.md
Expand Up @@ -9,6 +9,36 @@ This software works in all modern browsers as well as node.js via [npm](https://
Introduction
------------

A Linked Data Signature proof is created (or verified) by specifying a
signature suite and a proof purpose.

The signature suite performs the cryptographic operation required to sign (or
verify) a digital signature and includes information in a proof such as the
`verificationMethod` identifier (aka `creator`) and the date the proof was
created (aka `created`).

The proof purpose indicates why the proof was created and what its intended use
is. This information can also be used to make sure that the
`verificationMethod` was authorized for the stated purpose in the proof. Using
a proof purpose helps to encourage people to authorize certain cryptographic
keys (verification methods) for explicit purposes rather than granting them
ambient authority. This approach can help prevent people from accidentally
signing documents for reasons they did not intend.

This library provides base classes for signature suites and proof purposes
so that custom extensions can be written. It also provides some commonly
used signature suites and proof purposes.

This library also supports legacy signature suites such as `GraphSignature2012`,
`LinkedDataSignature2015`, and `EcdsaKoblitzSignature2016`. These signature
suites must be used with a `PublicKeyProofPurpose` instance as the proof
purpose as they were created before extensible proof purposes were possible.

During verification, the key and key controller information must be discovered.
This library allows for the key and key controller information to be looked up
via a `documentLoader` or it can be provided directly to the API via the
signature suite or proof purpose, respectively.

Install with npm:

```
Expand All @@ -17,9 +47,7 @@ npm install jsonld-signatures

In Node.js, include the library like this:
```js
var jsonld = require('jsonld');
var jsig = require('jsonld-signatures');
jsig.use('jsonld', jsonld);
const jsigs = require('jsonld-signatures');
```

In a browser environment, include `jsonld`, `forge`, and
Expand All @@ -28,33 +56,37 @@ In a browser environment, include `jsonld`, `forge`, and
Examples
--------

Signing and verifying a simple assertion:

```js
// to generate the next two lines, run the following command:
//
// openssl genrsa -out key.pem; cat key.pem; openssl rsa -in key.pem -pubout -out pubkey.pem; cat pubkey.pem; rm key.pem pubkey.pem
//
// for an example of how to specify these keys, look at [key-example]:
var testPublicKeyPem = "-----BEGIN PUBLIC KEY-----\r\n...";
var testPrivateKeyPem = "-----BEGIN PRIVATE KEY-----\r\n...";
const publicKeyPem = "-----BEGIN PUBLIC KEY-----\r\n...";
const privateKeyPem = "-----BEGIN PRIVATE KEY-----\r\n...";

// specify the public key object
var testPublicKey = {
'@context': jsig.SECURITY_CONTEXT_URL,
'@id': 'https://example.com/i/alice/keys/1',
owner: 'https://example.com/i/alice',
publicKeyPem: testPublicKeyPem
const publicKey = {
'@context': jsigs.SECURITY_CONTEXT_URL,
id: 'https://example.com/i/alice/keys/1',
controller: 'https://example.com/i/alice',
publicKeyPem
};

// specify the public key owner object
var testPublicKeyOwner = {
"@context": jsig.SECURITY_CONTEXT_URL,
'@id': 'https://example.com/i/alice',
publicKey: [testPublicKey]
// specify the public key controller object
const controller = {
'@context': jsigs.SECURITY_CONTEXT_URL,
id: 'https://example.com/i/alice',
publicKey: [publicKey]
// this authorizes this key to be used for making assertions
assertionMethod: [publicKey.id]
};

// create the JSON-LD document that should be signed
var testDocument = {
"@context": {
const doc = {
'@context': {
schema: 'http://schema.org/',
name: 'schema:name',
homepage: 'schema:url',
Expand All @@ -65,40 +97,95 @@ var testDocument = {
image: 'https://manu.sporny.org/images/manu.png'
};

// sign the document and then verify the signed document
jsig.sign(testDocument, {
privateKeyPem: testPrivateKeyPem,
creator: 'https://example.com/i/alice/keys/1'
}, function(err, signedDocument) {
if(err) {
return console.log('Signing error:', err);
}
console.log('Signed document:', signedDocument);

// verify the signed document
jsig.verify(signedDocument, {
publicKey: testPublicKey,
publicKeyOwner: testPublicKeyOwner,
}, function(err, verified) {
if(err) {
return console.log('Signature verification error:', err);
}
console.log('Signature is valid:', verified);
});
// sign the document as a simple assertion
const {RsaSignature2018} = jsigs.suites;
const {AuthenticationProofPurpose} = jsigs.purposes;
const {RSAKeyPair} = jsigs;
const key = new RSAKeyPair({...publicKey, privateKeyPem});
const signed = await jsigs.sign(doc, {
suite: new RsaSignature2018({key}),
purpose: new AssertionProofPurpose()
});

console.log('Signed document:', signed);

// verify the signed document
const result = await jsigs.verify(signed, {
suite: new RsaSignature2018(key),
purpose: new AssertionProofPurpose({controller})
});
if(result.verified) {
console.log('Signature verified.');
} else {
console.log('Signature verification error:', result.error);
}
```

Signing and verifying a document to authenticate to a website:

```js
const publicKeyBase58 = 'GycSSui454dpYRKiFdsQ5uaE8Gy3ac6dSMPcAoQsk8yq';
const privateKeyBase58 = '3Mmk4UzTRJTEtxaKk61LxtgUxAa2Dg36jF6Vog...SSiF';

// specify the public key object
const publicKey = {
'@context': jsigs.SECURITY_CONTEXT_URL,
id: 'https://example.com/i/alice/keys/2',
controller: 'https://example.com/i/alice',
publicKeyBase58
};

// specify the public key controller object
const controller = {
'@context': jsigs.SECURITY_CONTEXT_URL,
id: 'https://example.com/i/alice',
publicKey: [publicKey]
// this authorizes this key to be used for authenticating
authentication: [publicKey.id]
};

// create the JSON-LD document that should be signed
const doc = {
'@context': {
schema: 'http://schema.org/',
name: 'schema:action'
},
action: 'AuthenticateMe'
};

// verification
var sign = jsig.promises.sign(testDocument, {
privateKeyPem: testPrivateKeyPem,
creator: 'https://example.com/i/alice/keys/1'
// sign the document for the purpose of authentication
const {Ed25519Signature2018} = jsigs.suites;
const {AuthenticationProofPurpose} = jsigs.purposes;
const {Ed25519KeyPair} = jsigs;
const signed = await jsigs.sign(doc, {
suite: new Ed25519Signature2018({
verificationMethod: publicKey.id,
key: new Ed25519KeyPair({privateKeyPem})
}),
purpose: new AuthenticationProofPurpose({
challenge: 'abc',
domain: 'example.com'
})
});
sign.then(function(signedDocument) {...}, function(err) {...});

var verify = jsig.promises.verify(signedDocument, {
publicKey: testPublicKey,
publicKeyOwner: testPublicKeyOwner
console.log('Signed document:', signed);

// verify the signed document
const result = await jsigs.verify(signed, {
suite: new Ed25519Signature2018({
key: new Ed25519KeyPair(publicKey)
}),
purpose: new AuthenticationProofPurpose({
controller,
challenge: 'abc',
domain: 'example.com'
})
});
verify.then(function(verified) {...}, function(err) {...});
if(result.verified) {
console.log('Signature verified.');
} else {
console.log('Signature verification error:', result.error);
}
```

Commercial Support
Expand Down
36 changes: 20 additions & 16 deletions karma.conf.js
@@ -1,21 +1,15 @@
/**
* Karam configuration for jsonld-signatures.
*
* @author Dave Longley
* @author David I. Lehn
*
* Copyright (c) 2011-2017 Digital Bazaar, Inc. All rights reserved.
* Copyright (c) 2011-2018 Digital Bazaar, Inc. All rights reserved.
*/
const path = require('path');
const webpack = require('webpack');

module.exports = function(config) {
// bundler to test: webpack, browserify
var bundler = process.env.BUNDLER || 'webpack';
const bundler = process.env.BUNDLER || 'webpack';

var frameworks = ['mocha'];
const frameworks = ['mocha'];
// main bundle preprocessors
var preprocessors = ['babel'];
const preprocessors = ['babel'];

if(bundler === 'browserify') {
frameworks.push(bundler);
Expand All @@ -33,7 +27,7 @@ module.exports = function(config) {

// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: frameworks,
frameworks,

// list of files / patterns to load in the browser
files: [
Expand Down Expand Up @@ -62,15 +56,18 @@ module.exports = function(config) {
include: [{
// exclude node_modules by default
exclude: /(node_modules)/
}, {
// include rdf-canonize
}/*, {
// include jsonld and rdf-canonize
include: /(node_modules\/jsonld)/,
include: /(node_modules\/rdf-canonize)/
}],
}*/],
use: {
loader: 'babel-loader',
options: {
presets: ['env']
presets: ['env'],
plugins: [
['transform-object-rest-spread', {useBuiltIns: true}]
]
}
}
}
Expand All @@ -81,6 +78,13 @@ module.exports = function(config) {
process: false,
crypto: false,
setImmediate: false
},
resolve: {
alias: {
'bitcore-message':
require.resolve('bitcore-message/dist/bitcore-message.js'),
jsonld: require.resolve('jsonld/dist/jsonld.js')
}
}
},

Expand Down Expand Up @@ -111,7 +115,7 @@ module.exports = function(config) {
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
//browsers: ['PhantomJS', 'Chrome', 'Firefox', 'Safari'],
browsers: ['PhantomJS'],
browsers: ['ChromeHeadless'],

customLaunchers: {
IE9: {
Expand Down