Skip to content

Instantly share code, notes, and snippets.

@gjgd
Created February 12, 2020 15:05
Show Gist options
  • Save gjgd/11cac221f51a8a29c41af9ea482a18fe to your computer and use it in GitHub Desktop.
Save gjgd/11cac221f51a8a29c41af9ea482a18fe to your computer and use it in GitHub Desktop.
const { Ed25519KeyPair } = require('crypto-ld');
const { EdvClient } = require('edv-client');
const EdvInvoker = require('./EdvInvoker').default;
const EdvKak = require('./EdvKak').default;
const EdvHmac = require('./EdvHmac').default;
const axios = require('axios');
const { CapabilityDelegation } = require('ocapld');
const documentLoader = require('../../networking/documentLoader');
const jsigs = require('jsonld-signatures');
const { SECURITY_CONTEXT_V2_URL, sign, suites } = jsigs;
const { Ed25519Signature2018 } = suites;
// Use these if you're running "npm run serve:standalone" in packages/edv-server
const edvUrl = 'http://localhost:9876/edvs';
const resetUrl = 'http://localhost:9876/.well-known/reset';
// Use these if you're running "npm run start" in packages/edv-server
// const edvUrl = 'http://localhost:5010/did-edv/us-central1/main/edvs';
// const resetUrl = 'http://localhost:5010/did-edv/us-central1/main/.well-known/reset';
jest.setTimeout(10 * 1000);
const payload = {
'@context': [
'https://w3id.org/did/v1',
{
schema: 'http://schema.org/',
action: 'schema:action',
},
],
action: 'AuthenticateMe',
};
const keyAlice = {
controller: 'did:key:z6MknGnhiF3q3hFiZPMz5VaLPgea4dVcf86dPhmRkUF4UsBd',
id:
'did:key:z6MknGnhiF3q3hFiZPMz5VaLPgea4dVcf86dPhmRkUF4UsBd#z6MknGnhiF3q3hFiZPMz5VaLPgea4dVcf86dPhmRkUF4UsBd',
privateKeyBase58:
'5ciLFMSrPLAv5Kjw5PLTPTAindrSDgKSyTRJeQ3tafZJCy9je8aTWQe3aajUbcGWr5yMEz3r6Dni9gjvqGCkZkGP',
publicKeyBase58: '8pXf7zoPi9mFStXHPvcVYb6aF4DmFErGhgrVvCH3ZeQF',
type: 'Ed25519VerificationKey2018',
};
const keyBob = {
controller: 'did:key:z6Mkv6Cj2frAFsJgWuDByjBAecqqRdoNQ9SewqrRngKmgo6w',
id:
'did:key:z6Mkv6Cj2frAFsJgWuDByjBAecqqRdoNQ9SewqrRngKmgo6w#z6Mkv6Cj2frAFsJgWuDByjBAecqqRdoNQ9SewqrRngKmgo6w',
privateKeyBase58:
'33f4WHXwx9cgL4q8gbiYGr6TnY2CsQeo6Yibuhog6gaiTAmLWMfGd7NqDWHnJmSJ8hrVX5cJVZDDyPCU1AnTMtg7',
publicKeyBase58: 'GdwgSRbivKpDQQNVJADKoXHqc4XWzGCJFpwVxQMkmaKZ',
type: 'Ed25519VerificationKey2018',
};
describe('share', () => {
let clientAlice;
let encryptedDoc;
let keyAgreementKeyAlice;
let keyAgreementKeyBob;
let sharedWithBob;
const keyResolver = ({ id }) => {
if (keyAgreementKeyAlice.id === id) {
return keyAgreementKeyAlice;
}
if (keyAgreementKeyBob.id === id) {
return keyAgreementKeyBob;
}
throw new Error(`Key ${id} not found`);
};
beforeAll(async () => {
await axios.delete(resetUrl);
keyAgreementKeyAlice = new EdvKak(await Ed25519KeyPair.from(keyAlice));
keyAgreementKeyBob = new EdvKak(await Ed25519KeyPair.from(keyBob));
});
it('Alice creates an EDV', async () => {
const hmac = await EdvHmac.create();
const config = await EdvClient.createEdv({
url: edvUrl,
config: {
sequence: 0,
controller: keyAlice.controller,
keyAgreementKey: {
id: keyAgreementKeyAlice.id,
type: keyAgreementKeyAlice.type,
},
hmac: { id: hmac.id, type: hmac.type },
referenceId: 'primary',
},
});
clientAlice = new EdvClient({
id: config.id,
keyResolver,
keyAgreementKey: keyAgreementKeyAlice,
hmac,
});
expect(clientAlice).toBeDefined();
});
it('Alice creates a document in shared edv', async () => {
const docId = await EdvClient.generateId();
const doc = {
id: docId,
content: { payload: payload },
};
const invocationSigner = new EdvInvoker(keyAlice);
encryptedDoc = await clientAlice.update({
keyResolver,
invocationSigner,
recipients: [
{
header: {
kid: keyAgreementKeyAlice.id,
alg: 'ECDH-ES+A256KW',
},
},
{
header: {
kid: keyAgreementKeyBob.id,
alg: 'ECDH-ES+A256KW',
},
},
],
doc,
});
expect(encryptedDoc).toBeDefined();
expect(encryptedDoc.jwe.recipients).toHaveLength(2);
});
it('Bob can decrypt the encrypted document', async () => {
const clientBob = new EdvClient();
const decryptedDoc = await clientBob._decrypt({
encryptedDoc,
keyAgreementKey: keyAgreementKeyBob,
});
expect(decryptedDoc.content).toBeDefined();
expect(decryptedDoc.content.payload).toEqual(payload);
});
it('Alice generates a zcap for Bob to access her EDV', async () => {
const unsignedCapability = {
'@context': SECURITY_CONTEXT_V2_URL,
id: `urn:zcap:${await EdvClient.generateId()}`,
invocationTarget: `${clientAlice.id}/documents/${encryptedDoc.id}`,
invoker: keyBob.id,
allowedAction: 'read',
parentCapability: `${clientAlice.id}/zcaps/documents/${encryptedDoc.id}`,
};
const invocationSigner = new EdvInvoker(keyAlice);
const suite = new Ed25519Signature2018({
signer: invocationSigner,
verificationMethod: invocationSigner.id,
});
const purpose = new CapabilityDelegation({
capabilityChain: [unsignedCapability.parentCapability],
});
const zcap = await sign(unsignedCapability, {
documentLoader,
suite,
purpose,
});
await clientAlice.enableCapability({
capabilityToEnable: zcap,
invocationSigner,
});
sharedWithBob = {
clientId: clientAlice.id,
encryptedDocId: encryptedDoc.id,
capabilityId: zcap.id,
}
});
it('Bob can access the encrypted documents directly in the Edv', async () => {
const { clientId, encryptedDocId, capabilityId } = sharedWithBob;
const invocationSigner = new EdvInvoker(keyBob);
const clientBob = new EdvClient({
id: clientId,
keyResolver,
keyAgreementKey: keyAgreementKeyBob,
});
const delegatedDoc = await clientBob.get({
id: encryptedDocId,
invocationSigner,
capability: capabilityId,
});
expect(delegatedDoc).toBeDefined();
expect(delegatedDoc.content.payload).toEqual(payload);
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment