diff --git a/packages/daf-cli/src/identity-manager.ts b/packages/daf-cli/src/identity-manager.ts index 671056dcb..e865d2ffb 100644 --- a/packages/daf-cli/src/identity-manager.ts +++ b/packages/daf-cli/src/identity-manager.ts @@ -12,6 +12,8 @@ program .option('-d, --delete', 'Delete identity') .option('-s, --service', 'Add service endpoint') .option('-p, --publicKey', 'Add public key') + .option('--encrypt', 'Encrypt data to a recipient DID') + .option('--decrypt', 'Decrypt data') .action(async cmd => { if (cmd.types) { const list = await core.identityManager.getIdentityProviderTypes() @@ -136,4 +138,59 @@ program console.error(e) } } + + if (cmd.encrypt) { + try { + const identities = await core.identityManager.getIdentities() + const answers = await inquirer.prompt([ + { + type: 'list', + name: 'did', + choices: identities.map(item => item.did), + message: 'Select DID', + }, + { + type: 'text', + name: 'to', + message: 'Recipient DID', + }, + { + type: 'text', + name: 'message', + message: 'Message', + }, + ]) + + const identity = await core.identityManager.getIdentity(answers.did) + const result = await identity.encrypt(answers.to, answers.message) + console.log('Success:', result) + } catch (e) { + console.error(e) + } + } + + if (cmd.decrypt) { + try { + const identities = await core.identityManager.getIdentities() + const answers = await inquirer.prompt([ + { + type: 'list', + name: 'did', + choices: identities.map(item => item.did), + message: 'Select DID', + }, + { + type: 'text', + name: 'message', + message: 'Encrypted message', + }, + ]) + + const identity = await core.identityManager.getIdentity(answers.did) + const result = await identity.decrypt(answers.message) + console.log('Success:', result) + } catch (e) { + console.error(e) + } + } }) diff --git a/packages/daf-core/src/identity/abstract-identity.ts b/packages/daf-core/src/identity/abstract-identity.ts index 485fd1997..df92739a0 100644 --- a/packages/daf-core/src/identity/abstract-identity.ts +++ b/packages/daf-core/src/identity/abstract-identity.ts @@ -35,8 +35,8 @@ export abstract class AbstractIdentity { abstract did: string abstract didDoc(): Promise abstract signer(keyId?: string): Signer - abstract encrypt(to: string, data: string | Uint8Array): Promise - abstract decrypt(encrypted: any): Promise + abstract encrypt(to: string, data: string): Promise + abstract decrypt(encrypted: string): Promise } type AbstractIdentityClass = typeof AbstractIdentity diff --git a/packages/daf-ethr-did-fs/package-lock.json b/packages/daf-ethr-did-fs/package-lock.json index a34d119f9..31c6b4764 100644 --- a/packages/daf-ethr-did-fs/package-lock.json +++ b/packages/daf-ethr-did-fs/package-lock.json @@ -4,6 +4,35 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@types/libsodium-wrappers": { + "version": "0.7.7", + "resolved": "https://registry.npmjs.org/@types/libsodium-wrappers/-/libsodium-wrappers-0.7.7.tgz", + "integrity": "sha512-Li91pVKcLvQJK3ZolwCPo85oxf2gKBCApgnesRxYg4OVYchLXcJB2eivX8S87vfQVv6ZRnyCO1lLDosZGJfpRg==" + }, + "DIDComm-js": { + "version": "github:decentralized-identity/DIDComm-js#c8ca38df0b78c03d4e3c7e4cde13bd0a933e284a", + "from": "github:decentralized-identity/DIDComm-js", + "requires": { + "@types/libsodium-wrappers": "^0.7.5", + "base-58": "0.0.1", + "libsodium-wrappers": "^0.7.5" + }, + "dependencies": { + "libsodium-wrappers": { + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/libsodium-wrappers/-/libsodium-wrappers-0.7.6.tgz", + "integrity": "sha512-OUO2CWW5bHdLr6hkKLHIKI4raEkZrf3QHkhXsJ1yCh6MZ3JDA7jFD3kCATNquuGSG6MjjPHQIQms0y0gBDzjQg==", + "requires": { + "libsodium": "0.7.6" + } + } + } + }, + "base-58": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/base-58/-/base-58-0.0.1.tgz", + "integrity": "sha1-hdPnAlEHVmGTM4j4MdHri49jFOM=" + }, "bn.js": { "version": "4.11.8", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", @@ -53,7 +82,14 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "js-sha3": { - "version": "0.8.0" + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", + "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==" + }, + "libsodium": { + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/libsodium/-/libsodium-0.7.6.tgz", + "integrity": "sha512-hPb/04sEuLcTRdWDtd+xH3RXBihpmbPCsKW/Jtf4PsvdyKh+D6z2D2gvp/5BfoxseP+0FCOg66kE+0oGUE/loQ==" }, "minimalistic-assert": { "version": "1.0.1", diff --git a/packages/daf-ethr-did-fs/package.json b/packages/daf-ethr-did-fs/package.json index 26527a616..df8a2eae3 100644 --- a/packages/daf-ethr-did-fs/package.json +++ b/packages/daf-ethr-did-fs/package.json @@ -8,6 +8,7 @@ "build": "tsc" }, "dependencies": { + "DIDComm-js": "github:decentralized-identity/DIDComm-js", "base64url": "^3.0.1", "daf-core": "^1.4.1", "daf-resolver": "^1.1.0", diff --git a/packages/daf-ethr-did-fs/src/ethr-identity.ts b/packages/daf-ethr-did-fs/src/ethr-identity.ts index 5cd8b4bce..a4c369fe9 100644 --- a/packages/daf-ethr-did-fs/src/ethr-identity.ts +++ b/packages/daf-ethr-did-fs/src/ethr-identity.ts @@ -1,6 +1,8 @@ import { AbstractIdentity, Resolver } from 'daf-core' import { SimpleSigner } from 'did-jwt' import { Key } from './identity-provider' +import { DIDComm } from 'DIDComm-js' +const didcomm = new DIDComm() export class EthrIdentity extends AbstractIdentity { public readonly did: string @@ -18,13 +20,39 @@ export class EthrIdentity extends AbstractIdentity { public signer(keyId?: string) { const key = this.keys.find(item => item.type === 'Secp256k1') - if (!key) throw Error('[ethr-identity] Key not found') + if (!key) throw Error('Key not found') return SimpleSigner(key.privateKey) } async didDoc() { return this.resolver.resolve(this.did) } - async encrypt(): Promise {} - async decrypt(): Promise {} + async encrypt(to: string, data: string): Promise { + const didDoc = await this.resolver.resolve(to) + const publicKey = didDoc?.publicKey.find(item => item.type == 'Ed25519VerificationKey2018') + if (publicKey?.publicKeyHex) { + await didcomm.ready + return await didcomm.pack_anon_msg_for_recipients(data, [ + Uint8Array.from(Buffer.from(publicKey.publicKeyHex, 'hex')), + ]) + } else { + return Promise.reject('Encryption public key not found for ' + to) + } + } + async decrypt(encrypted: string): Promise { + const key = this.keys.find(item => item.type === 'Ed25519') + if (!key) throw Error('Encryption key not found for ' + this.did) + await didcomm.ready + try { + const unpackMessage = await didcomm.unpackMessage(encrypted, { + keyType: 'ed25519', + publicKey: Uint8Array.from(Buffer.from(key.publicKey, 'hex')), + privateKey: Uint8Array.from(Buffer.from(key.privateKey, 'hex')), + }) + + return unpackMessage.message + } catch (e) { + return Promise.reject('Error: ' + e.message) + } + } }