diff --git a/src/identities/identities.js b/src/identities/identities.js index 768b6f1..5a07718 100644 --- a/src/identities/identities.js +++ b/src/identities/identities.js @@ -44,6 +44,7 @@ const Identities = async ({ keystore, identityKeysPath, storage, ipfs } = {}) => id: idSignature, publicKey: publicKeyAndIdSignature } + const identity = await Identity({ id, publicKey, signatures, type, sign, verify }) await storage.put(identity.hash, identity.bytes) @@ -57,8 +58,8 @@ const Identities = async ({ keystore, identityKeysPath, storage, ipfs } = {}) => } const { id, publicKey, signatures } = identity - const idSignatureVerified = await KeyStore.verify(signatures.id, publicKey, id) + const idSignatureVerified = await KeyStore.verify(signatures.id, publicKey, id) if (!idSignatureVerified) { return false } @@ -69,8 +70,8 @@ const Identities = async ({ keystore, identityKeysPath, storage, ipfs } = {}) => } const Provider = getProviderFor(identity.type) - const identityVerified = await Provider.verifyIdentity(identity) + const identityVerified = await Provider.verifyIdentity(identity) if (identityVerified) { await verifiedIdentitiesCache.put(signatures.id, identity) } diff --git a/src/identities/identity.js b/src/identities/identity.js index 098ed72..6f521b8 100644 --- a/src/identities/identity.js +++ b/src/identities/identity.js @@ -9,29 +9,12 @@ const hasher = sha256 const hashStringEncoding = base58btc const Identity = async ({ id, publicKey, signatures, type, sign, verify } = {}) => { - if (!isDefined(id)) { - throw new Error('Identity id is required') - } - - if (!isDefined(publicKey)) { - throw new Error('Invalid public key') - } - - if (!isDefined(signatures)) { - throw new Error('Signatures is required') - } - - if (!isDefined(signatures.id)) { - throw new Error('Signature of the id is required') - } - - if (!isDefined(signatures.publicKey)) { - throw new Error('Signature of (publicKey + idSignature) is required') - } - - if (!isDefined(type)) { - throw new Error('Identity type is required') - } + if (!isDefined(id)) throw new Error('Identity id is required') + if (!isDefined(publicKey)) throw new Error('Invalid public key') + if (!isDefined(signatures)) throw new Error('Signatures object is required') + if (!isDefined(signatures.id)) throw new Error('Signature of id is required') + if (!isDefined(signatures.publicKey)) throw new Error('Signature of publicKey+id is required') + if (!isDefined(type)) throw new Error('Identity type is required') signatures = Object.assign({}, signatures) diff --git a/src/identities/providers/did.js b/src/identities/providers/did.js index 9c77736..ce266bc 100644 --- a/src/identities/providers/did.js +++ b/src/identities/providers/did.js @@ -2,32 +2,39 @@ import IdentityProvider from './interface.js' import * as u8a from 'uint8arrays' import { DID } from 'dids' -const TYPE = 'DID' +const type = 'DID' class DIDIdentityProvider extends IdentityProvider { constructor ({ didProvider }) { super() + + if (!didProvider) { + throw new Error('DIDIdentityProvider requires a didProvider parameter') + } + this.did = new DID({ resolver: DIDIdentityProvider.did._resolver, provider: didProvider }) } - static get type () { - return TYPE - } + static get type () { return type } - async getId ({ space }) { - if (!this.did.authenticated) await this.did.authenticate() + async getId () { + if (!this.did.authenticated) { + await this.did.authenticate() + } return this.did.id } - async signIdentity (data, { space }) { - if (!this.did.authenticated) await this.did.authenticate() + async signIdentity (data) { + if (!this.did.authenticated) { + await this.did.authenticate() + } const payload = u8a.toString(u8a.fromString(data, 'base16'), 'base64url') - const jws = await this.did.createJWS(payload) + const { signatures } = await this.did.createJWS(payload) // encode as JWS with detached payload - return `${jws.signatures[0].protected}..${jws.signatures[0].signature}` + return `${signatures[0].protected}..${signatures[0].signature}` } static setDIDResolver (resolver) { @@ -42,15 +49,19 @@ class DIDIdentityProvider extends IdentityProvider { if (!this.did) { throw new Error('The DID resolver must first be set with setDIDResolver()') } - const data = identity.publicKey + identity.signatures.id + + const { publicKey, signatures } = identity + const data = publicKey + signatures.id + try { const payload = u8a.toString(u8a.fromString(data, 'base16'), 'base64url') - const [header, signature] = identity.signatures.publicKey.split('..') + const [header, signature] = signatures.publicKey.split('..') const jws = [header, payload, signature].join('.') await this.did.verifyJWS(jws) } catch (e) { return false } + return true } } diff --git a/src/identities/providers/ethereum.js b/src/identities/providers/ethereum.js index bfdb791..afb22b4 100644 --- a/src/identities/providers/ethereum.js +++ b/src/identities/providers/ethereum.js @@ -1,11 +1,12 @@ import IdentityProvider from './interface.js' import { Wallet, verifyMessage } from '@ethersproject/wallet' + const type = 'ethereum' class EthIdentityProvider extends IdentityProvider { - constructor (options = {}) { + constructor ({ wallet } = {}) { super() - this.wallet = options.wallet + this.wallet = wallet } // Returns the type of the identity provider @@ -20,16 +21,22 @@ class EthIdentityProvider extends IdentityProvider { } // Returns a signature of pubkeysignature - async signIdentity (data, options = {}) { + async signIdentity (data) { const wallet = this.wallet - if (!wallet) { throw new Error('wallet is required') } + + if (!wallet) { + throw new Error('wallet is required') + } return wallet.signMessage(data) } static async verifyIdentity (identity) { // Verify that identity was signed by the id - const signerAddress = verifyMessage(identity.publicKey + identity.signatures.id, identity.signatures.publicKey) + const signerAddress = verifyMessage( + identity.publicKey + identity.signatures.id, + identity.signatures.publicKey + ) return (signerAddress === identity.id) } @@ -38,17 +45,24 @@ class EthIdentityProvider extends IdentityProvider { if (!options.mnemonicOpts.mnemonic) { throw new Error('mnemonic is required') } - return Wallet.fromMnemonic(options.mnemonicOpts.mnemonic, options.mnemonicOpts.path, options.mnemonicOpts.wordlist) + + const { mnemonic, path, wordlist } = options.mnemonicOpts + return Wallet.fromMnemonic(mnemonic, path, wordlist) } + if (options.encryptedJsonOpts) { if (!options.encryptedJsonOpts.json) { throw new Error('encrypted json is required') } + if (!options.encryptedJsonOpts.password) { throw new Error('password for encrypted json is required') } - return Wallet.fromEncryptedJson(options.encryptedJsonOpts.json, options.encryptedJsonOpts.password, options.encryptedJsonOpts.progressCallback) + + const { json, password, progressCallback } = options.encryptedJsonOpts + return Wallet.fromEncryptedJson(json, password, progressCallback) } + return Wallet.createRandom() } } diff --git a/src/identities/providers/interface.js b/src/identities/providers/interface.js index 44a76a9..a524f16 100644 --- a/src/identities/providers/interface.js +++ b/src/identities/providers/interface.js @@ -14,7 +14,7 @@ class IdentityProvider { } /* - Return the type for this identity-procider + Return the type for this identity-proider NOTE! This is the only property of the interface that shouldn't be overridden in the inherited IdentityProvider */ diff --git a/src/identities/providers/orbitdb.js b/src/identities/providers/orbitdb.js index ff55605..3664638 100644 --- a/src/identities/providers/orbitdb.js +++ b/src/identities/providers/orbitdb.js @@ -1,37 +1,36 @@ import IdentityProvider from './interface.js' import KeyStore from '../../key-store.js' + const type = 'orbitdb' class OrbitDBIdentityProvider extends IdentityProvider { constructor ({ keystore }) { super() + if (!keystore) { - throw new Error('OrbitDBIdentityProvider requires a keystore') + throw new Error('OrbitDBIdentityProvider requires a keystore parameter') } + this._keystore = keystore } // Returns the type of the identity provider static get type () { return type } - async getId (options = {}) { - const id = options.id + async getId ({ id } = {}) { if (!id) { throw new Error('id is required') } - - const keystore = this._keystore - const key = await keystore.getKey(id) || await keystore.createKey(id) + const key = await this._keystore.getKey(id) || await this._keystore.createKey(id) return Buffer.from(key.public.marshal()).toString('hex') } - async signIdentity (data, options = {}) { - const id = options.id + async signIdentity (data, { id } = {}) { if (!id) { throw new Error('id is required') } - const keystore = this._keystore - const key = await keystore.getKey(id) + + const key = await this._keystore.getKey(id) if (!key) { throw new Error(`Signing key for '${id}' not found`) } @@ -40,12 +39,9 @@ class OrbitDBIdentityProvider extends IdentityProvider { } static async verifyIdentity (identity) { + const { id, publicKey, signatures } = identity // Verify that identity was signed by the ID - return KeyStore.verify( - identity.signatures.publicKey, - identity.id, - identity.publicKey + identity.signatures.id - ) + return KeyStore.verify(signatures.publicKey, id, publicKey + signatures.id) } } diff --git a/src/oplog/entry.js b/src/oplog/entry.js index 8616303..1b22ee8 100644 --- a/src/oplog/entry.js +++ b/src/oplog/entry.js @@ -7,7 +7,7 @@ import { isDefined } from '../utils/index.js' /* * @description - * An ipfs-log entry + * A Log entry */ const codec = dagCbor diff --git a/test/identities/identity.test.js b/test/identities/identity.test.js index 6e93994..6724dbe 100644 --- a/test/identities/identity.test.js +++ b/test/identities/identity.test.js @@ -71,7 +71,7 @@ describe('Identity', function () { } catch (e) { err = e.toString() } - assert.strictEqual(err, 'Error: Signatures is required') + assert.strictEqual(err, 'Error: Signatures object is required') }) it('throws and error if signature for id was not given in constructor', async () => { @@ -81,7 +81,7 @@ describe('Identity', function () { } catch (e) { err = e.toString() } - assert.strictEqual(err, 'Error: Signature of the id is required') + assert.strictEqual(err, 'Error: Signature of id is required') }) it('throws and error if signature for publicKey was not given in constructor', async () => { @@ -91,7 +91,7 @@ describe('Identity', function () { } catch (e) { err = e.toString() } - assert.strictEqual(err, 'Error: Signature of (publicKey + idSignature) is required') + assert.strictEqual(err, 'Error: Signature of publicKey+id is required') }) it('throws and error if signature for publicKey was not given in constructor', async () => { @@ -101,7 +101,7 @@ describe('Identity', function () { } catch (e) { err = e.toString() } - assert.strictEqual(err, 'Error: Signature of the id is required') + assert.strictEqual(err, 'Error: Signature of id is required') }) // it('throws and error if identity provider was not given in constructor', async () => {