From 5b6a70c7cc5f0ad8bf10c3b8fd09fed4cbdf0376 Mon Sep 17 00:00:00 2001 From: haad Date: Thu, 16 Feb 2023 16:40:46 +0200 Subject: [PATCH 1/6] Refactor IdentityProvider --- src/identities/identities.js | 135 +++++++++++ src/identities/identity-provider.js | 177 --------------- src/identities/identity.js | 30 +-- src/identities/index.js | 2 +- src/identities/providers/orbitdb.js | 4 +- src/index.js | 2 +- src/key-store.js | 57 +++-- src/oplog/entry.js | 2 +- src/oplog/log.js | 9 +- test/document-store.spec.js | 11 +- test/event-store.spec.js | 33 ++- test/feed.spec.js | 33 ++- test/fixtures/orbit-db-identity-keys.js | 38 +--- test/identities/did-identity-provider.spec.js | 43 ++-- .../ethereum-identity-provider.spec.js | 39 ++-- test/identities/identity-provider.spec.js | 214 +++++++++++------- test/identities/identity.spec.js | 24 +- test/keyvalue.spec.js | 32 ++- test/oplog/append.test.js | 9 +- test/oplog/crdt.test.js | 15 +- test/oplog/entry.test.js | 14 +- test/oplog/heads.test.js | 8 +- test/oplog/iterator.test.js | 14 +- test/oplog/join-concurrent.test.js | 11 +- test/oplog/join.test.js | 17 +- test/oplog/load.test.js | 4 +- test/oplog/log.test.js | 8 +- test/oplog/references.test.js | 8 +- test/oplog/replicate.test.js | 40 ++-- test/oplog/signed-log.test.js | 24 +- test/storage.spec.js | 8 +- 31 files changed, 539 insertions(+), 526 deletions(-) create mode 100644 src/identities/identities.js delete mode 100644 src/identities/identity-provider.js diff --git a/src/identities/identities.js b/src/identities/identities.js new file mode 100644 index 0000000..c7f27a6 --- /dev/null +++ b/src/identities/identities.js @@ -0,0 +1,135 @@ +import Identity from './identity.js' +import OrbitDBIdentityProvider from './providers/orbitdb.js' +// import DIDIdentityProvider from './identity-providers/did.js' +// import EthIdentityProvider from './identity-providers/ethereum.js' +import KeyStore from '../key-store.js' +import IdentityStore from './identity-store.js' +import { LRUStorage } from '../storage/index.js' +import path from 'path' + +const DefaultProviderType = 'orbitdb' +const DefaultIdentityKeysPath = path.join('./orbitdb', 'identity', 'identitykeys') + +const supportedTypes = { + orbitdb: OrbitDBIdentityProvider + // [DIDIdentityProvider.type]: DIDIdentityProvider, + // [EthIdentityProvider.type]: EthIdentityProvider +} + +const Identities = async ({ keystore, signingKeyStore, identityKeysPath, signingKeysPath, identityStore, ipfs } = {}) => { + keystore = keystore || new KeyStore(identityKeysPath || DefaultIdentityKeysPath) + signingKeyStore = signingKeyStore || (signingKeysPath ? new KeyStore(signingKeysPath) : keystore) + identityStore = identityStore || await IdentityStore({ ipfs }) + + const verifiedIdentitiesCache = await LRUStorage({ size: 1000 }) + + const getIdentity = async (hash) => { + return identityStore.get(hash) + } + + const createIdentity = async (options = {}) => { + options.keystore = signingKeyStore || keystore + + const type = options.type || DefaultProviderType + const Provider = getProviderFor(type) + const identityProvider = new Provider(options) + const id = await identityProvider.getId(options) + + const privateKey = await keystore.getKey(id) || await keystore.createKey(id) + const publicKey = keystore.getPublic(privateKey) + const idSignature = await KeyStore.sign(privateKey, id) + const pubKeyIdSignature = await identityProvider.signIdentity(publicKey + idSignature, options) + const identity = new Identity(id, publicKey, idSignature, pubKeyIdSignature, type, sign, verify) + + const hash = await identityStore.put(identity.toJSON()) + // TODO: fix this monkey patching + identity.hash = hash + + return identity + } + + const verifyIdentity = async (identity) => { + if (!Identity.isIdentity(identity)) { + return false + } + + const { id, publicKey, signatures } = identity + const idSignatureVerified = await KeyStore.verify(signatures.id, publicKey, id) + + if (!idSignatureVerified) { + return false + } + + const verifiedIdentity = await verifiedIdentitiesCache.get(signatures.id) + if (verifiedIdentity) { + return Identity.isEqual(identity, verifiedIdentity) + } + + const Provider = getProviderFor(identity.type) + const identityVerified = await Provider.verifyIdentity(identity) + + if (identityVerified) { + await verifiedIdentitiesCache.put(signatures.id, identity.toJSON()) + } + + return identityVerified + } + + const sign = async (identity, data) => { + const signingKey = await keystore.getKey(identity.id) + + if (!signingKey) { + throw new Error('Private signing key not found from KeyStore') + } + + return KeyStore.sign(signingKey, data) + } + + const verify = async (signature, publicKey, data) => { + return KeyStore.verify(signature, publicKey, data) + } + + const isSupported = (type) => { + return Object.keys(supportedTypes).includes(type) + } + + const getProviderFor = (type) => { + if (!isSupported(type)) { + throw new Error(`IdentityProvider type '${type}' is not supported`) + } + + return supportedTypes[type] + } + + const addIdentityProvider = (IdentityProvider) => { + if (!IdentityProvider) { + throw new Error('IdentityProvider must be given as an argument') + } + + if (!IdentityProvider.type || + typeof IdentityProvider.type !== 'string') { + throw new Error('Given IdentityProvider doesn\'t have a field \'type\'') + } + + supportedTypes[IdentityProvider.type] = IdentityProvider + } + + const removeIdentityProvider = (type) => { + delete supportedTypes[type] + } + + return { + createIdentity, + verifyIdentity, + getIdentity, + sign, + verify, + isSupported, + addIdentityProvider, + removeIdentityProvider, + keystore, + signingKeyStore + } +} + +export { Identities as default } diff --git a/src/identities/identity-provider.js b/src/identities/identity-provider.js deleted file mode 100644 index b1db0fa..0000000 --- a/src/identities/identity-provider.js +++ /dev/null @@ -1,177 +0,0 @@ -import Identity from './identity.js' -import IdentityProvider from './providers/interface.js' -import OrbitDBIdentityProvider from './providers/orbitdb.js' -// import DIDIdentityProvider from './identity-providers/did.js' -// import EthIdentityProvider from './identity-providers/ethereum.js' -import KeyStore from '../key-store.js' -import IdentityStore from './identity-store.js' -import LRU from 'lru' -import path from 'path' - -const defaultType = 'orbitdb' -const identityKeysPath = path.join('./orbitdb', 'identity', 'identitykeys') - -const supportedTypes = { - orbitdb: OrbitDBIdentityProvider - // [DIDIdentityProvider.type]: DIDIdentityProvider, - // [EthIdentityProvider.type]: EthIdentityProvider -} - -const getHandlerFor = (type) => { - if (!Identities.isSupported(type)) { - throw new Error(`IdentityProvider type '${type}' is not supported`) - } - return supportedTypes[type] -} - -class Identities { - constructor (options) { - this._keystore = options.keystore - this._signingKeyStore = options.signingKeyStore || this._keystore - this._knownIdentities = options.cache || new LRU(options.cacheSize || 100) - this._storage = options.identityStore - } - - static get IdentityProvider () { return IdentityProvider } - - get keystore () { return this._keystore } - - get signingKeyStore () { return this._signingKeyStore } - - async sign (identity, data) { - const signingKey = await this.keystore.getKey(identity.id) - if (!signingKey) { - throw new Error('Private signing key not found from KeyStore') - } - const sig = await this.keystore.sign(signingKey, data) - return sig - } - - async verify (signature, publicKey, data, verifier = 'v1') { - return this.keystore.verify(signature, publicKey, data, verifier) - } - - async createIdentity (options = {}) { - const keystore = options.keystore || this.keystore - const type = options.type || defaultType - const identityProvider = type === defaultType ? new OrbitDBIdentityProvider(options.signingKeyStore || keystore) : new (getHandlerFor(type))(options) - const id = await identityProvider.getId(options) - - const { publicKey, idSignature } = await this.signId(id) - const pubKeyIdSignature = await identityProvider.signIdentity(publicKey + idSignature, options) - // return new Identity(id, publicKey, idSignature, pubKeyIdSignature, type, this) - const identity = new Identity(id, publicKey, idSignature, pubKeyIdSignature, type, this) - await identity.store() - // const hash = options.identityStore.put(identity.toJSON()) - return identity - } - - async get (hash) { - return this._storage.get(hash) - } - - async signId (id) { - const keystore = this.keystore - const key = await keystore.getKey(id) || await keystore.createKey(id) - const publicKey = keystore.getPublic(key) - const idSignature = await keystore.sign(key, id) - return { publicKey, idSignature } - } - - async verifyIdentity (identity) { - if (!Identity.isIdentity(identity)) { - return false - } - - const knownID = this._knownIdentities.get(identity.signatures.id) - if (knownID) { - return identity.id === knownID.id && - identity.publicKey === knownID.publicKey && - identity.signatures.id === knownID.signatures.id && - identity.signatures.publicKey === knownID.signatures.publicKey - } - - const verifyIdSig = await this.keystore.verify( - identity.signatures.id, - identity.publicKey, - identity.id - ) - if (!verifyIdSig) return false - - const IdentityProvider = getHandlerFor(identity.type) - const verified = await IdentityProvider.verifyIdentity(identity) - if (verified) { - this._knownIdentities.set(identity.signatures.id, Identity.toJSON(identity)) - } - - return verified - } - - static async verifyIdentity (identity) { - if (!Identity.isIdentity(identity)) { - return false - } - - const verifyIdSig = await KeyStore.verify( - identity.signatures.id, - identity.publicKey, - identity.id - ) - - if (!verifyIdSig) return false - - const IdentityProvider = getHandlerFor(identity.type) - return IdentityProvider.verifyIdentity(identity) - } - - static async createIdentity (options = {}) { - if (!options.keystore) { - options.keystore = new KeyStore(options.identityKeysPath || identityKeysPath) - } - if (!options.signingKeyStore) { - if (options.signingKeysPath) { - options.signingKeyStore = new KeyStore(options.signingKeysPath) - } else { - options.signingKeyStore = options.keystore - } - } - await options.keystore.open() - await options.signingKeyStore.open() - - let identityStore - if (options.storage) { - identityStore = await IdentityStore({ storage: options.storage }) - } else if (options.ipfs) { - identityStore = await IdentityStore({ ipfs: options.ipfs }) - } else { - identityStore = await IdentityStore() - } - - options = Object.assign({}, { type: defaultType, identityStore }, options) - const identities = new Identities(options) - return identities.createIdentity(options) - } - - static isSupported (type) { - return Object.keys(supportedTypes).includes(type) - } - - static addIdentityProvider (IdentityProvider) { - if (!IdentityProvider) { - throw new Error('IdentityProvider class needs to be given as an option') - } - - if (!IdentityProvider.type || - typeof IdentityProvider.type !== 'string') { - throw new Error('Given IdentityProvider class needs to implement: static get type() { /* return a string */ }.') - } - - supportedTypes[IdentityProvider.type] = IdentityProvider - } - - static removeIdentityProvider (type) { - delete supportedTypes[type] - } -} - -export { Identities as default, Identity } diff --git a/src/identities/identity.js b/src/identities/identity.js index f4807cf..a70408c 100644 --- a/src/identities/identity.js +++ b/src/identities/identity.js @@ -1,7 +1,7 @@ import isDefined from '../utils/is-defined.js' class Identity { - constructor (id, publicKey, idSignature, pubKeyIdSignature, type, provider) { + constructor (id, publicKey, idSignature, pubKeyIdSignature, type, signFn, verifyFn) { if (!isDefined(id)) { throw new Error('Identity id is required') } @@ -22,21 +22,18 @@ class Identity { throw new Error('Identity type is required') } - if (!isDefined(provider)) { - throw new Error('Identity provider is required') - } + // if (!isDefined(provider)) { + // throw new Error('Identity provider is required') + // } this._id = id this._publicKey = publicKey this._signatures = Object.assign({}, { id: idSignature }, { publicKey: pubKeyIdSignature }) this._type = type - this._provider = provider + // this._provider = provider this.hash = null - } - - async store () { - const value = this.toJSON() - this.hash = await this._provider._storage.put(value) + this.sign = signFn + this.verify = verifyFn } /** @@ -59,9 +56,9 @@ class Identity { return this._type } - get provider () { - return this._provider - } + // get provider () { + // return this._provider + // } toJSON () { return { @@ -72,6 +69,13 @@ class Identity { } } + static isEqual (a, b) { + return a.id === b.id && + a.publicKey === b.publicKey && + a.signatures.id === b.signatures.id && + a.signatures.publicKey === b.signatures.publicKey + } + static isIdentity (identity) { return identity.id !== undefined && identity.publicKey !== undefined && diff --git a/src/identities/index.js b/src/identities/index.js index 66cb49e..2a17e62 100644 --- a/src/identities/index.js +++ b/src/identities/index.js @@ -1,2 +1,2 @@ -export { default as IdentityProvider } from './identity-provider.js' +export { default as Identities } from './identities.js' export { default as Identity } from './identity.js' diff --git a/src/identities/providers/orbitdb.js b/src/identities/providers/orbitdb.js index cacc565..ff55605 100644 --- a/src/identities/providers/orbitdb.js +++ b/src/identities/providers/orbitdb.js @@ -3,7 +3,7 @@ import KeyStore from '../../key-store.js' const type = 'orbitdb' class OrbitDBIdentityProvider extends IdentityProvider { - constructor (keystore) { + constructor ({ keystore }) { super() if (!keystore) { throw new Error('OrbitDBIdentityProvider requires a keystore') @@ -36,7 +36,7 @@ class OrbitDBIdentityProvider extends IdentityProvider { throw new Error(`Signing key for '${id}' not found`) } - return keystore.sign(key, data) + return KeyStore.sign(key, data) } static async verifyIdentity (identity) { diff --git a/src/index.js b/src/index.js index 86f7371..4b76e4b 100644 --- a/src/index.js +++ b/src/index.js @@ -1,3 +1,3 @@ export { Log, DefaultAccessController, Entry } from './oplog/index.js' export { default as KeyStore } from './key-store.js' -export { IdentityProvider } from './identities/index.js' +export { Identities } from './identities/index.js' diff --git a/src/key-store.js b/src/key-store.js index d81b260..d8029e5 100644 --- a/src/key-store.js +++ b/src/key-store.js @@ -108,9 +108,10 @@ export default class KeyStore { if (!id) { throw new Error('id needed to create a key') } - if (this._store.status && this._store.status !== 'open') { - return null - } + // if (this._store.status && this._store.status !== 'open') { + // console.log("22::", id) + // return null + // } // Generate a private key const privKey = ec.genKeyPair({ entropy }).getPrivate().toArrayLike(Buffer) @@ -175,22 +176,6 @@ export default class KeyStore { return unmarshal(Buffer.from(deserializedKey.privateKey, 'hex')) } - async sign (key, data) { - if (!key) { - throw new Error('No signing key given') - } - - if (!data) { - throw new Error('Given input data was undefined') - } - - if (!Buffer.isBuffer(data)) { - data = Buffer.from(data) - } - - return Buffer.from(await key.sign(data)).toString('hex') - } - getPublic (keys, options = {}) { const formats = ['hex', 'buffer'] const decompress = typeof options.decompress === 'undefined' ? true : options.decompress @@ -206,11 +191,23 @@ export default class KeyStore { return format === 'buffer' ? pubKey : pubKey.toString('hex') } - async verify (signature, publicKey, data, v = 'v1') { - return KeyStore.verify(signature, publicKey, data, v) + static async sign (key, data) { + if (!key) { + throw new Error('No signing key given') + } + + if (!data) { + throw new Error('Given input data was undefined') + } + + if (!Buffer.isBuffer(data)) { + data = Buffer.from(data) + } + + return Buffer.from(await key.sign(data)).toString('hex') } - static async verify (signature, publicKey, data, v = 'v1') { + static async verify (signature, publicKey, data) { // const cached = verifiedCache.get(signature) const cached = null let res = false @@ -221,16 +218,16 @@ export default class KeyStore { // verifiedCache.set(signature, { publicKey, data }) // } } else { - const compare = (cached, data, v) => { - let match - if (v === 'v0') { - match = Buffer.compare(Buffer.alloc(30, cached), Buffer.alloc(30, data)) === 0 - } else { - match = Buffer.isBuffer(data) ? Buffer.compare(cached, data) === 0 : cached === data - } + const compare = (cached, data) => { + // let match + // if (v === 'v0') { + // match = Buffer.compare(Buffer.alloc(30, cached), Buffer.alloc(30, data)) === 0 + // } else { + const match = Buffer.isBuffer(data) ? Buffer.compare(cached, data) === 0 : cached === data + // } return match } - res = cached.publicKey === publicKey && compare(cached.data, data, v) + res = cached.publicKey === publicKey && compare(cached.data, data) } return res } diff --git a/src/oplog/entry.js b/src/oplog/entry.js index afcfd09..51c4a01 100644 --- a/src/oplog/entry.js +++ b/src/oplog/entry.js @@ -46,7 +46,7 @@ const create = async (identity, id, payload, clock = null, next = [], refs = []) } const { bytes } = await Block.encode({ value: entry, codec, hasher }) - const signature = await identity.provider.sign(identity, bytes) + const signature = await identity.sign(identity, bytes) entry.key = identity.publicKey entry.identity = identity.hash diff --git a/src/oplog/log.js b/src/oplog/log.js index 8a53bc4..c8b5704 100644 --- a/src/oplog/log.js +++ b/src/oplog/log.js @@ -29,7 +29,7 @@ const DefaultStorage = MemoryStorage const DefaultAccessController = async () => { // An AccessController may do any async initialization stuff here... return { - canAppend: async (entry, identityProvider) => true + canAppend: async (entry) => true } } @@ -153,7 +153,7 @@ const Log = async (identity, { logId, logHeads, access, entryStorage, headsStora refs ) // Authorize the entry - const canAppend = await access.canAppend(entry, identity.provider) + const canAppend = await access.canAppend(entry) if (!canAppend) { throw new Error(`Could not append entry:\nKey "${identity.hash}" is not allowed to write to the log`) } @@ -208,18 +208,17 @@ const Log = async (identity, { logId, logHeads, access, entryStorage, headsStora if (isAlreadyInTheLog) { return false } - const identityProvider = identity.provider // Check that the Entry belongs to this Log if (entry.id !== id) { throw new Error(`Entry's id (${entry.id}) doesn't match the log's id (${id}).`) } // Verify if entry is allowed to be added to the log - const canAppend = await access.canAppend(entry, identityProvider) + const canAppend = await access.canAppend(entry) if (!canAppend) { throw new Error(`Could not append entry:\nKey "${entry.identity}" is not allowed to write to the log`) } // Verify signature for the entry - const isValid = await Entry.verify(identityProvider, entry) + const isValid = await Entry.verify(identity, entry) if (!isValid) { throw new Error(`Could not validate signature for entry "${entry.hash}"`) } diff --git a/test/document-store.spec.js b/test/document-store.spec.js index 698de3e..4adf65c 100644 --- a/test/document-store.spec.js +++ b/test/document-store.spec.js @@ -1,7 +1,6 @@ import { deepStrictEqual, strictEqual } from 'assert' import rimraf from 'rimraf' import { Log, Entry } from '../src/oplog/index.js' -import { IdentityProvider } from '../src/identities/index.js' import KeyStore from '../src/key-store.js' import { DocumentStore, Database } from '../src/db/index.js' import { IPFSBlockStorage, LevelStorage } from '../src/storage/index.js' @@ -13,7 +12,6 @@ import connectPeers from './utils/connect-nodes.js' import { identityKeys, signingKeys, createTestIdentities, cleanUpTestIdentities } from './fixtures/orbit-db-identity-keys.js' const { sync: rmrf } = rimraf -const { createIdentity } = IdentityProvider const OpLog = { Log, Entry, IPFSBlockStorage, LevelStorage } @@ -25,6 +23,7 @@ Object.keys(testAPIs).forEach((IPFS) => { let ipfs1, ipfs2 let keystore, signingKeyStore // let peerId1, peerId2 + let identities1, identities2 let testIdentity1, testIdentity2 let db1, db2 @@ -43,7 +42,9 @@ Object.keys(testAPIs).forEach((IPFS) => { // peerId1 = await getIpfsPeerId(ipfs1) // peerId2 = await getIpfsPeerId(ipfs2) - const testIdentities = await createTestIdentities(ipfs1, ipfs2) + const [identities, testIdentities] = await createTestIdentities(ipfs1, ipfs2) + identities1 = identities[0] + identities2 = identities[1] testIdentity1 = testIdentities[0] testIdentity2 = testIdentities[1] @@ -54,7 +55,7 @@ Object.keys(testAPIs).forEach((IPFS) => { beforeEach(async () => { const accessController = { canAppend: async (entry) => { - const identity = await testIdentity1.provider.get(entry.identity) + const identity = await identities1.getIdentity(entry.identity) return identity.id === testIdentity1.id } } @@ -74,7 +75,7 @@ Object.keys(testAPIs).forEach((IPFS) => { }) after(async () => { - await cleanUpTestIdentities([testIdentity1, testIdentity2]) + await cleanUpTestIdentities([identities1, identities1]) if (ipfsd1) { await stopIpfs(ipfsd1) diff --git a/test/event-store.spec.js b/test/event-store.spec.js index 9da5082..44cc513 100644 --- a/test/event-store.spec.js +++ b/test/event-store.spec.js @@ -1,7 +1,7 @@ import { deepStrictEqual, strictEqual } from 'assert' import rimraf from 'rimraf' import { Log, Entry } from '../src/oplog/index.js' -import { IdentityProvider } from '../src/identities/index.js' +import { Identities } from '../src/identities/index.js' import KeyStore from '../src/key-store.js' import { EventStore, Database } from '../src/db/index.js' import { IPFSBlockStorage, LevelStorage } from '../src/storage/index.js' @@ -13,7 +13,7 @@ import waitFor from './utils/wait-for.js' import { identityKeys, signingKeys, createTestIdentities, cleanUpTestIdentities } from './fixtures/orbit-db-identity-keys.js' const { sync: rmrf } = rimraf -const { createIdentity } = IdentityProvider +const { createIdentity } = Identities const OpLog = { Log, Entry, IPFSBlockStorage, LevelStorage } @@ -25,11 +25,20 @@ Object.keys(testAPIs).forEach((IPFS) => { let ipfs1, ipfs2 let keystore, signingKeyStore let peerId1, peerId2 + let identities1, identities2 let testIdentity1, testIdentity2 let kv1, kv2 const databaseId = 'events-AAA' + const accessController = { + canAppend: async (entry) => { + const identity = await identities1.getIdentity(entry.identity) + return identity.id === testIdentity1.id + } + } + + before(async () => { // Start two IPFS instances ipfsd1 = await startIpfs(IPFS, config.daemon1) @@ -43,7 +52,9 @@ Object.keys(testAPIs).forEach((IPFS) => { peerId1 = await getIpfsPeerId(ipfs1) peerId2 = await getIpfsPeerId(ipfs2) - const testIdentities = await createTestIdentities(ipfs1, ipfs2) + const [identities, testIdentities] = await createTestIdentities(ipfs1, ipfs2) + identities1 = identities[0] + identities2 = identities[1] testIdentity1 = testIdentities[0] testIdentity2 = testIdentities[1] @@ -63,7 +74,7 @@ Object.keys(testAPIs).forEach((IPFS) => { }) after(async () => { - await cleanUpTestIdentities([testIdentity1, testIdentity2]) + await cleanUpTestIdentities([identities1, identities2]) if (ipfsd1) { await stopIpfs(ipfsd1) @@ -93,13 +104,6 @@ Object.keys(testAPIs).forEach((IPFS) => { let updateCount = 0 // let syncCount = 0 - const accessController = { - canAppend: async (entry) => { - const identity = await testIdentity1.provider.get(entry.identity) - return identity.id === testIdentity1.id - } - } - const onUpdate = (entry) => { // console.log(".", updateCount, entry.payload) ++updateCount @@ -204,13 +208,6 @@ Object.keys(testAPIs).forEach((IPFS) => { let updateCount = 0 // let syncCount = 0 - const accessController = { - canAppend: async (entry) => { - const identity = await testIdentity1.provider.get(entry.identity) - return identity.id === testIdentity1.id - } - } - const onUpdate = (entry) => { ++updateCount } diff --git a/test/feed.spec.js b/test/feed.spec.js index 90837e8..ec97c9c 100644 --- a/test/feed.spec.js +++ b/test/feed.spec.js @@ -1,7 +1,7 @@ import { deepStrictEqual, strictEqual } from 'assert' import rimraf from 'rimraf' import { Log, Entry } from '../src/oplog/index.js' -import { IdentityProvider } from '../src/identities/index.js' +import { Identities } from '../src/identities/index.js' import KeyStore from '../src/key-store.js' import { Feed, Database } from '../src/db/index.js' import { IPFSBlockStorage, LevelStorage } from '../src/storage/index.js' @@ -13,7 +13,7 @@ import waitFor from './utils/wait-for.js' import { identityKeys, signingKeys, createTestIdentities, cleanUpTestIdentities } from './fixtures/orbit-db-identity-keys.js' const { sync: rmrf } = rimraf -const { createIdentity } = IdentityProvider +const { createIdentity } = Identities const OpLog = { Log, Entry, IPFSBlockStorage, LevelStorage } Object.keys(testAPIs).forEach((IPFS) => { @@ -24,11 +24,20 @@ Object.keys(testAPIs).forEach((IPFS) => { let ipfs1, ipfs2 let keystore, signingKeyStore let peerId1, peerId2 + let identities1, identities2 let testIdentity1, testIdentity2 let kv1, kv2 const databaseId = 'feed-AAA' + const accessController = { + canAppend: async (entry) => { + const identity = await identities1.getIdentity(entry.identity) + return identity.id === testIdentity1.id + } + } + + before(async () => { // Start two IPFS instances ipfsd1 = await startIpfs(IPFS, config.daemon1) @@ -42,7 +51,9 @@ Object.keys(testAPIs).forEach((IPFS) => { peerId1 = await getIpfsPeerId(ipfs1) peerId2 = await getIpfsPeerId(ipfs2) - const testIdentities = await createTestIdentities(ipfs1, ipfs2) + const [identities, testIdentities] = await createTestIdentities(ipfs1, ipfs2) + identities1 = identities[0] + identities2 = identities[1] testIdentity1 = testIdentities[0] testIdentity2 = testIdentities[1] @@ -62,7 +73,7 @@ Object.keys(testAPIs).forEach((IPFS) => { }) after(async () => { - await cleanUpTestIdentities([testIdentity1, testIdentity2]) + await cleanUpTestIdentities([identities1, identities2]) if (ipfsd1) { await stopIpfs(ipfsd1) @@ -92,13 +103,6 @@ Object.keys(testAPIs).forEach((IPFS) => { let updateCount = 0 // let syncCount = 0 - const accessController = { - canAppend: async (entry) => { - const identity = await testIdentity1.provider.get(entry.identity) - return identity.id === testIdentity1.id - } - } - const onUpdate = (entry) => { ++updateCount } @@ -202,13 +206,6 @@ Object.keys(testAPIs).forEach((IPFS) => { let updateCount = 0 // let syncCount = 0 - const accessController = { - canAppend: async (entry) => { - const identity = await testIdentity1.provider.get(entry.identity) - return identity.id === testIdentity1.id - } - } - const onUpdate = (entry) => { ++updateCount } diff --git a/test/fixtures/orbit-db-identity-keys.js b/test/fixtures/orbit-db-identity-keys.js index 05c6c95..79217ed 100644 --- a/test/fixtures/orbit-db-identity-keys.js +++ b/test/fixtures/orbit-db-identity-keys.js @@ -1,8 +1,7 @@ import KeyStore from '../../src/key-store.js' -import { IdentityProvider } from '../../src/identities/index.js' +import { Identities } from '../../src/identities/index.js' import rimraf from 'rimraf' -const { createIdentity } = IdentityProvider const { sync: rmrf } = rimraf import userA from "./keys/identity-keys/03e0480538c2a39951d054e17ff31fde487cb1031d0044a037b53ad2e028a3e77c.json" assert { type: "json" } @@ -46,39 +45,18 @@ const createTestIdentities = async (ipfs1, ipfs2) => { } // Create an identity for each peers - const testIdentity1 = await createIdentity({ id: 'userA', keystore, signingKeyStore, ipfs: ipfs1 }) - const testIdentity2 = await createIdentity({ id: 'userB', keystore, signingKeyStore, ipfs: ipfs2 }) + const identities1 = await Identities({ keystore, signingKeyStore, ipfs: ipfs1 }) + const identities2 = await Identities({ keystore, signingKeyStore, ipfs: ipfs2 }) + const testIdentity1 = await identities1.createIdentity({ id: 'userA' }) + const testIdentity2 = await identities2.createIdentity({ id: 'userB' }) - return [testIdentity1, testIdentity2] -} - -const createTestIdentitiesInMemory = async (ipfs1 = null, ipfs2 = null) => { - rmrf('./keys_1') - rmrf('./keys_2') - - const keystore = new KeyStore('./keys_1') - // await keystore.open() - for (const [key, value] of Object.entries(identityKeys)) { - await keystore.addKey(key, value) - } - - const signingKeyStore = new KeyStore('./keys_2') - // await signingKeyStore.open() - for (const [key, value] of Object.entries(signingKeys)) { - await signingKeyStore.addKey(key, value) - } - - // Create an identity for each peers - const testIdentity1 = await createIdentity({ id: 'userA', keystore, signingKeyStore, ipfs: ipfs1 }) - const testIdentity2 = await createIdentity({ id: 'userB', keystore, signingKeyStore, ipfs: ipfs2 }) - - return [testIdentity1, testIdentity2] + return [[identities1, identities2], [testIdentity1, testIdentity2]] } const cleanUpTestIdentities = async (identities) => { for (let identity of identities) { - await identity.provider._keystore.close() - await identity.provider._signingKeyStore.close() + await identity.keystore.close() + await identity.signingKeyStore.close() } } diff --git a/test/identities/did-identity-provider.spec.js b/test/identities/did-identity-provider.spec.js index a8f1859..8ededdf 100644 --- a/test/identities/did-identity-provider.spec.js +++ b/test/identities/did-identity-provider.spec.js @@ -1,12 +1,12 @@ import assert from 'assert' import path from 'path' import rmrf from 'rimraf' -import { KeyStore, IdentityProvider } from '../../src/index.js' +import { KeyStore, Identities } from '../../src/index.js' import { Identity } from '../../src/identities/index.js' import { Ed25519Provider } from 'key-did-provider-ed25519' import KeyDidResolver from 'key-did-resolver' import DIDIdentityProvider from '../../src/identities/providers/did.js' -const keypath = path.resolve('./test/identies/fixtures/keys') +const keypath = path.resolve('./test/identities/fixtures/keys') let keystore const seed = new Uint8Array([157, 94, 116, 198, 19, 248, 93, 239, 173, 82, 245, 222, 199, 7, 183, 177, 123, 238, 83, 240, 143, 188, 87, 191, 33, 95, 58, 136, 46, 218, 219, 245]) @@ -14,15 +14,20 @@ const didStr = 'did:key:z6MkpnTJwrrVuphNh1uKb5DB7eRxvqniVaSDUHU6jtGVmn3r' const type = DIDIdentityProvider.type describe('DID Identity Provider', function () { + let identities + before(async () => { - DIDIdentityProvider.setDIDResolver(KeyDidResolver.getResolver()) - IdentityProvider.addIdentityProvider(DIDIdentityProvider) keystore = new KeyStore(keypath) await keystore.open() + identities = await Identities({ keystore }) + DIDIdentityProvider.setDIDResolver(KeyDidResolver.getResolver()) + identities.addIdentityProvider(DIDIdentityProvider) }) after(async () => { - await keystore.close() + if (keystore) { + await keystore.close() + } }) describe('create an DID identity', () => { @@ -30,7 +35,7 @@ describe('DID Identity Provider', function () { before(async () => { const didProvider = new Ed25519Provider(seed) - identity = await IdentityProvider.createIdentity({ type, keystore, didProvider }) + identity = await identities.createIdentity({ type, keystore, didProvider }) }) it('has the correct id', async () => { @@ -50,7 +55,7 @@ describe('DID Identity Provider', function () { it('has a signature for the id', async () => { const signingKey = await keystore.getKey(didStr) - const idSignature = await keystore.sign(signingKey, didStr) + const idSignature = await KeyStore.sign(signingKey, didStr) const verifies = await KeyStore.verify(idSignature, identity.publicKey, didStr) assert.strictEqual(verifies, true) assert.strictEqual(identity.signatures.id, idSignature) @@ -58,7 +63,7 @@ describe('DID Identity Provider', function () { it('has a signature for the publicKey', async () => { const signingKey = await keystore.getKey(didStr) - const idSignature = await keystore.sign(signingKey, didStr) + const idSignature = await KeyStore.sign(signingKey, didStr) assert.notStrictEqual(idSignature, undefined) }) }) @@ -68,17 +73,17 @@ describe('DID Identity Provider', function () { before(async () => { const didProvider = new Ed25519Provider(seed) - identity = await IdentityProvider.createIdentity({ type, keystore, didProvider }) + identity = await identities.createIdentity({ type, keystore, didProvider }) }) it('DID identity verifies', async () => { - const verified = await IdentityProvider.verifyIdentity(identity) + const verified = await identities.verifyIdentity(identity) assert.strictEqual(verified, true) }) it('DID identity with incorrect id does not verify', async () => { const identity2 = new Identity('NotAnId', identity.publicKey, identity.signatures.id, identity.signatures.publicKey, identity.type, identity.provider) - const verified = await IdentityProvider.verifyIdentity(identity2) + const verified = await identities.verifyIdentity(identity2) assert.strictEqual(verified, false) }) }) @@ -89,13 +94,13 @@ describe('DID Identity Provider', function () { before(async () => { const didProvider = new Ed25519Provider(seed) - identity = await IdentityProvider.createIdentity({ type, keystore, didProvider }) + identity = await identities.createIdentity({ type, keystore, didProvider }) }) it('sign data', async () => { const signingKey = await keystore.getKey(identity.id) - const expectedSignature = await keystore.sign(signingKey, data) - const signature = await identity.provider.sign(identity, data, keystore) + const expectedSignature = await KeyStore.sign(signingKey, data) + const signature = await identities.sign(identity, data, keystore) assert.strictEqual(signature, expectedSignature) }) @@ -105,7 +110,7 @@ describe('DID Identity Provider', function () { let signature let err try { - signature = await identity.provider.sign(modifiedIdentity, data, keystore) + signature = await identities.sign(modifiedIdentity, data, keystore) } catch (e) { err = e.toString() } @@ -120,17 +125,17 @@ describe('DID Identity Provider', function () { before(async () => { const didProvider = new Ed25519Provider(seed) - identity = await IdentityProvider.createIdentity({ type, keystore, didProvider }) - signature = await identity.provider.sign(identity, data, keystore) + identity = await identities.createIdentity({ type, keystore, didProvider }) + signature = await identities.sign(identity, data, keystore) }) it('verifies that the signature is valid', async () => { - const verified = await identity.provider.verify(signature, identity.publicKey, data) + const verified = await identities.verify(signature, identity.publicKey, data) assert.strictEqual(verified, true) }) it('doesn\'t verify invalid signature', async () => { - const verified = await identity.provider.verify('invalid', identity.publicKey, data) + const verified = await identities.verify('invalid', identity.publicKey, data) assert.strictEqual(verified, false) }) }) diff --git a/test/identities/ethereum-identity-provider.spec.js b/test/identities/ethereum-identity-provider.spec.js index 1223642..e055344 100644 --- a/test/identities/ethereum-identity-provider.spec.js +++ b/test/identities/ethereum-identity-provider.spec.js @@ -1,7 +1,7 @@ import assert from 'assert' import path from 'path' import rmrf from 'rimraf' -import { KeyStore, IdentityProvider } from '../../src/index.js' +import { KeyStore, Identities } from '../../src/index.js' import { Identity } from '../../src/identities/index.js' import EthIdentityProvider from '../../src/identities/providers/ethereum.js' @@ -10,14 +10,19 @@ let keystore const type = EthIdentityProvider.type describe('Ethereum Identity Provider', function () { + let identities + before(async () => { - IdentityProvider.addIdentityProvider(EthIdentityProvider) keystore = new KeyStore(keypath) await keystore.open() + identities = await Identities({ keystore }) + identities.addIdentityProvider(EthIdentityProvider) }) after(async () => { - await keystore.close() + if (keystore) { + await keystore.close() + } }) describe('create an ethereum identity', () => { @@ -27,7 +32,7 @@ describe('Ethereum Identity Provider', function () { before(async () => { const ethIdentityProvider = new EthIdentityProvider() wallet = await ethIdentityProvider._createWallet() - identity = await IdentityProvider.createIdentity({ type, keystore, wallet }) + identity = await identities.createIdentity({ type, keystore, wallet }) }) it('has the correct id', async () => { @@ -47,7 +52,7 @@ describe('Ethereum Identity Provider', function () { it('has a signature for the id', async () => { const signingKey = await keystore.getKey(wallet.address) - const idSignature = await keystore.sign(signingKey, wallet.address) + const idSignature = await KeyStore.sign(signingKey, wallet.address) const verifies = await KeyStore.verify(idSignature, Buffer.from(signingKey.public.marshal()).toString('hex'), wallet.address) assert.strictEqual(verifies, true) assert.strictEqual(identity.signatures.id, idSignature) @@ -55,7 +60,7 @@ describe('Ethereum Identity Provider', function () { it('has a signature for the publicKey', async () => { const signingKey = await keystore.getKey(wallet.address) - const idSignature = await keystore.sign(signingKey, wallet.address) + const idSignature = await KeyStore.sign(signingKey, wallet.address) const publicKeyAndIdSignature = await wallet.signMessage(identity.publicKey + idSignature) assert.strictEqual(identity.signatures.publicKey, publicKeyAndIdSignature) }) @@ -65,17 +70,17 @@ describe('Ethereum Identity Provider', function () { let identity before(async () => { - identity = await IdentityProvider.createIdentity({ keystore, type }) + identity = await identities.createIdentity({ keystore, type }) }) it('ethereum identity verifies', async () => { - const verified = await IdentityProvider.verifyIdentity(identity) + const verified = await identities.verifyIdentity(identity) assert.strictEqual(verified, true) }) it('ethereum identity with incorrect id does not verify', async () => { const identity2 = new Identity('NotAnId', identity.publicKey, identity.signatures.id, identity.signatures.publicKey, identity.type, identity.provider) - const verified = await IdentityProvider.verifyIdentity(identity2) + const verified = await identities.verifyIdentity(identity2) assert.strictEqual(verified, false) }) }) @@ -85,13 +90,13 @@ describe('Ethereum Identity Provider', function () { const data = 'hello friend' before(async () => { - identity = await IdentityProvider.createIdentity({ keystore, type }) + identity = await identities.createIdentity({ keystore, type }) }) it('sign data', async () => { const signingKey = await keystore.getKey(identity.id) - const expectedSignature = await keystore.sign(signingKey, data) - const signature = await identity.provider.sign(identity, data, keystore) + const expectedSignature = await KeyStore.sign(signingKey, data) + const signature = await identities.sign(identity, data, keystore) assert.strictEqual(signature, expectedSignature) }) @@ -101,7 +106,7 @@ describe('Ethereum Identity Provider', function () { let signature let err try { - signature = await identity.provider.sign(modifiedIdentity, data, keystore) + signature = await identities.sign(modifiedIdentity, data, keystore) } catch (e) { err = e.toString() } @@ -115,17 +120,17 @@ describe('Ethereum Identity Provider', function () { let signature before(async () => { - identity = await IdentityProvider.createIdentity({ type, keystore }) - signature = await identity.provider.sign(identity, data, keystore) + identity = await identities.createIdentity({ type, keystore }) + signature = await identities.sign(identity, data, keystore) }) it('verifies that the signature is valid', async () => { - const verified = await identity.provider.verify(signature, identity.publicKey, data) + const verified = await identities.verify(signature, identity.publicKey, data) assert.strictEqual(verified, true) }) it('doesn\'t verify invalid signature', async () => { - const verified = await identity.provider.verify('invalid', identity.publicKey, data) + const verified = await identities.verify('invalid', identity.publicKey, data) assert.strictEqual(verified, false) }) }) diff --git a/test/identities/identity-provider.spec.js b/test/identities/identity-provider.spec.js index f22f45c..19805a2 100644 --- a/test/identities/identity-provider.spec.js +++ b/test/identities/identity-provider.spec.js @@ -1,7 +1,7 @@ import assert from 'assert' import path from 'path' import rmrf from 'rimraf' -import { KeyStore, IdentityProvider } from '../../src/index.js' +import { KeyStore, Identities } from '../../src/index.js' import { Identity } from '../../src/identities/index.js' import fs from 'fs-extra' const fixturesPath = path.resolve('./test/identities/fixtures/keys') @@ -21,43 +21,66 @@ describe('Identity Provider', function () { rmrf.sync(identityKeysPath) }) - describe('Creating IdentityProvider', () => { + describe('Creating Identities', () => { const id = 'A' + + let identities let identity + afterEach(async () => { + if (identities) { + await identities.keystore.close() + } + if (identities) { + await identities.signingKeyStore.close() + } + }) + it('identityKeysPath only - has the correct id', async () => { - identity = await IdentityProvider.createIdentity({ id, identityKeysPath }) - const key = await identity.provider.keystore.getKey(id) + identities = await Identities({ identityKeysPath }) + identity = await identities.createIdentity({ id }) + const key = await identities.keystore.getKey(id) const externalId = Buffer.from(key.public.marshal()).toString('hex') assert.strictEqual(identity.id, externalId) }) it('identityKeysPath and signingKeysPath - has a different id', async () => { - identity = await IdentityProvider.createIdentity({ id, identityKeysPath, signingKeysPath }) - const key = await identity.provider.keystore.getKey(id) + identities = await Identities({ identityKeysPath, signingKeysPath }) + identity = await identities.createIdentity({ id }) + const key = await identities.keystore.getKey(id) const externalId = Buffer.from(key.public.marshal()).toString('hex') assert.notStrictEqual(identity.id, externalId) }) - - afterEach(async () => { - await identity.provider.keystore.close() - await identity.provider.signingKeyStore.close() - }) }) describe('Passing in custom keystore', async () => { - const id = 'B'; let identity; let keystore; let signingKeyStore + const id = 'B' + + let identity + let identities + let keystore + let signingKeyStore before(async () => { keystore = new KeyStore(identityKeysPath) await keystore.open() signingKeyStore = new KeyStore(signingKeysPath) await signingKeyStore.open() + identities = await Identities({ keystore }) + }) + + after(async () => { + if (keystore) { + await keystore.close() + } + if (signingKeyStore) { + await signingKeyStore.close() + } }) it('has the correct id', async () => { - identity = await IdentityProvider.createIdentity({ id, keystore }) - keystore = identity.provider._keystore + identity = await identities.createIdentity({ id }) + keystore = identities.keystore const key = await keystore.getKey(id) const externalId = Buffer.from(key.public.marshal()).toString('hex') assert.strictEqual(identity.id, externalId) @@ -81,7 +104,7 @@ describe('Identity Provider', function () { const key = await keystore.getKey(id) const externalId = Buffer.from(key.public.marshal()).toString('hex') const signingKey = await keystore.getKey(externalId) - const idSignature = await keystore.sign(signingKey, externalId) + const idSignature = await KeyStore.sign(signingKey, externalId) const publicKey = Buffer.from(signingKey.public.marshal()).toString('hex') const verifies = await KeyStore.verify(idSignature, publicKey, externalId) assert.strictEqual(verifies, true) @@ -92,41 +115,42 @@ describe('Identity Provider', function () { const key = await keystore.getKey(id) const externalId = Buffer.from(key.public.marshal()).toString('hex') const signingKey = await keystore.getKey(externalId) - const idSignature = await keystore.sign(signingKey, externalId) + const idSignature = await KeyStore.sign(signingKey, externalId) const externalKey = await keystore.getKey(id) - const publicKeyAndIdSignature = await keystore.sign(externalKey, identity.publicKey + idSignature) + const publicKeyAndIdSignature = await KeyStore.sign(externalKey, identity.publicKey + idSignature) assert.strictEqual(identity.signatures.publicKey, publicKeyAndIdSignature) }) - - after(async () => { - await keystore.close() - await signingKeyStore.close() - }) }) describe('create an identity with saved keys', () => { - let keystore, signingKeyStore - - let savedKeysKeyStore, identity const id = 'QmPhnEjVkYE1Ym7F5MkRUfkD6NtuSptE7ugu1Ggr149W2X' const expectedPublicKey = '040d78ff62afb656ac62db1aae3b1536a614991e28bb4d721498898b7d4194339640cd18c37b259e2c77738de0d6f9a5d52e0b936611de6b6ba78891a8b2a38317' const expectedIdSignature = '30450221009de7b91952d73f577e85962aa6301350865212e3956862f80f4ebb626ffc126b022027d57415fb145b7e06cf06320fbfa63ea98a958b065726fe86eaab809a6bf607' const expectedPkIdSignature = '304402202806e7c2406ca1f35961d38adc3997c179e142d54e1ca838ace373fae27124fd02200d6ca3aea6e1341bf5e4e0b84b559bbeefecfade34115de266a69d04d924905e' - before(async () => { - keystore = new KeyStore(identityKeysPath) - await keystore.open() - signingKeyStore = new KeyStore(signingKeysPath) - await signingKeyStore.open() + let identities + let identity + let savedKeysKeyStore + before(async () => { await fs.copy(fixturesPath, savedKeysPath) + savedKeysKeyStore = new KeyStore(savedKeysPath) await savedKeysKeyStore.open() - identity = await IdentityProvider.createIdentity({ id, keystore: savedKeysKeyStore }) + + identities = await Identities({ keystore: savedKeysKeyStore }) + identity = await identities.createIdentity({ id }) }) + after(async () => { + if (identities) { + await identities.keystore.close() + } + if (identities) { + await identities.signingKeyStore.close() + } rmrf.sync(savedKeysPath) }) @@ -154,21 +178,20 @@ describe('Identity Provider', function () { it('has the correct signatures', async () => { const internalSigningKey = await savedKeysKeyStore.getKey(identity.id) const externalSigningKey = await savedKeysKeyStore.getKey(id) - const idSignature = await savedKeysKeyStore.sign(internalSigningKey, identity.id) - const pubKeyIdSignature = await savedKeysKeyStore.sign(externalSigningKey, identity.publicKey + idSignature) + const idSignature = await KeyStore.sign(internalSigningKey, identity.id) + const pubKeyIdSignature = await KeyStore.sign(externalSigningKey, identity.publicKey + idSignature) const expectedSignature = { id: idSignature, publicKey: pubKeyIdSignature } assert.deepStrictEqual(identity.signatures, expectedSignature) }) - - after(async () => { - await keystore.close() - await signingKeyStore.close() - }) }) describe('verify identity\'s signature', () => { const id = 'QmFoo' - let identity, keystore, signingKeyStore + + let identities + let identity + let keystore + let signingKeyStore before(async () => { keystore = new KeyStore(identityKeysPath) @@ -177,14 +200,25 @@ describe('Identity Provider', function () { await signingKeyStore.open() }) + after(async () => { + if (keystore) { + await keystore.close() + } + if (signingKeyStore) { + await signingKeyStore.close() + } + }) + it('identity pkSignature verifies', async () => { - identity = await IdentityProvider.createIdentity({ id, type, keystore, signingKeyStore }) + identities = await Identities({ keystore, signingKeyStore }) + identity = await identities.createIdentity({ id, type }) const verified = await KeyStore.verify(identity.signatures.id, identity.publicKey, identity.id) assert.strictEqual(verified, true) }) it('identity signature verifies', async () => { - identity = await IdentityProvider.createIdentity({ id, type, keystore, signingKeyStore }) + identities = await Identities({ keystore, signingKeyStore }) + identity = await identities.createIdentity({ id, type }) const verified = await KeyStore.verify(identity.signatures.publicKey, identity.id, identity.publicKey + identity.signatures.id) assert.strictEqual(verified, true) }) @@ -200,85 +234,102 @@ describe('Identity Provider', function () { static get type () { return 'fake' } } - IdentityProvider.addIdentityProvider(IP) - identity = await IdentityProvider.createIdentity({ type: IP.type, keystore, signingKeyStore }) - const verified = await IdentityProvider.verifyIdentity(identity) + identities.addIdentityProvider(IP) + identity = await identities.createIdentity({ type: IP.type }) + const verified = await identities.verifyIdentity(identity) assert.strictEqual(verified, false) }) - - after(async () => { - await keystore.close() - await signingKeyStore.close() - }) }) describe('verify identity', () => { const id = 'QmFoo' - let identity, keystore, signingKeyStore + + let identities + let identity + let keystore + let signingKeyStore before(async () => { keystore = new KeyStore(identityKeysPath) await keystore.open() signingKeyStore = new KeyStore(signingKeysPath) await signingKeyStore.open() - }) - - it('identity verifies', async () => { - identity = await IdentityProvider.createIdentity({ id, type, keystore, signingKeyStore }) - const verified = await identity.provider.verifyIdentity(identity) - assert.strictEqual(verified, true) + identities = await Identities({ keystore, signingKeyStore }) }) after(async () => { - await keystore.close() - await signingKeyStore.close() + if (keystore) { + await keystore.close() + } + if (signingKeyStore) { + await signingKeyStore.close() + } + }) + + it('identity verifies', async () => { + identity = await identities.createIdentity({ id, type }) + const verified = await identities.verifyIdentity(identity) + assert.strictEqual(verified, true) }) }) describe('sign data with an identity', () => { const id = '0x01234567890abcdefghijklmnopqrstuvwxyz' const data = 'hello friend' - let identity, keystore, signingKeyStore + + let identities + let identity + let keystore + let signingKeyStore before(async () => { keystore = new KeyStore(identityKeysPath) await keystore.open() signingKeyStore = new KeyStore(signingKeysPath) await signingKeyStore.open() - identity = await IdentityProvider.createIdentity({ id, keystore, signingKeyStore }) + identities = await Identities({ keystore, signingKeyStore }) + identity = await identities.createIdentity({ id }) + }) + + after(async () => { + if (keystore) { + await keystore.close() + } + if (signingKeyStore) { + await signingKeyStore.close() + } }) it('sign data', async () => { const signingKey = await keystore.getKey(identity.id) - const expectedSignature = await keystore.sign(signingKey, data) - const signature = await identity.provider.sign(identity, data, keystore) + const expectedSignature = await KeyStore.sign(signingKey, data) + const signature = await identities.sign(identity, data, keystore) assert.strictEqual(signature, expectedSignature) }) it('throws an error if private key is not found from keystore', async () => { // Remove the key from the keystore (we're using a mock storage in these tests) - const modifiedIdentity = new Identity('this id does not exist', identity.publicKey, '', identity.signatures, identity.type, identity.provider) + const modifiedIdentity = new Identity('this id does not exist', identity.publicKey, '', identity.signatures, identity.type) let signature let err try { - signature = await identity.provider.sign(modifiedIdentity, data, keystore) + signature = await identities.sign(modifiedIdentity, data, keystore) } catch (e) { err = e.toString() } assert.strictEqual(signature, undefined) assert.strictEqual(err, 'Error: Private signing key not found from KeyStore') }) - - after(async () => { - await keystore.close() - await signingKeyStore.close() - }) }) describe('verify data signed by an identity', () => { const id = '03602a3da3eb35f1148e8028f141ec415ef7f6d4103443edbfec2a0711d716f53f' const data = 'hello friend' - let identity, keystore, signingKeyStore + + let identities + let identity + let keystore + let signingKeyStore let signature before(async () => { @@ -288,24 +339,29 @@ describe('Identity Provider', function () { await signingKeyStore.open() }) + after(async () => { + if (keystore) { + await keystore.close() + } + if (signingKeyStore) { + await signingKeyStore.close() + } + }) + beforeEach(async () => { - identity = await IdentityProvider.createIdentity({ id, type, keystore, signingKeyStore }) - signature = await identity.provider.sign(identity, data, keystore) + identities = await Identities({ keystore, signingKeyStore }) + identity = await identities.createIdentity({ id, type }) + signature = await identities.sign(identity, data, keystore) }) it('verifies that the signature is valid', async () => { - const verified = await identity.provider.verify(signature, identity.publicKey, data) + const verified = await identities.verify(signature, identity.publicKey, data) assert.strictEqual(verified, true) }) it('doesn\'t verify invalid signature', async () => { - const verified = await identity.provider.verify('invalid', identity.publicKey, data) + const verified = await identities.verify('invalid', identity.publicKey, data) assert.strictEqual(verified, false) }) - - after(async () => { - await keystore.close() - await signingKeyStore.close() - }) }) }) diff --git a/test/identities/identity.spec.js b/test/identities/identity.spec.js index 0d03e16..c92ac2b 100644 --- a/test/identities/identity.spec.js +++ b/test/identities/identity.spec.js @@ -31,9 +31,9 @@ describe('Identity', function () { assert.strictEqual(identity.signatures.publicKey, publicKeyAndIdSignature) }) - it('has the correct provider', async () => { - assert.deepStrictEqual(identity.provider, provider) - }) + // it('has the correct provider', async () => { + // assert.deepStrictEqual(identity.provider, provider) + // }) it('converts identity to a JSON object', async () => { const expected = { @@ -86,15 +86,15 @@ describe('Identity', function () { assert.strictEqual(err, 'Error: Signature of (publicKey + idSignature) is required') }) - it('throws and error if identity provider was not given in constructor', async () => { - let err - try { - identity = new Identity('abc', publicKey, idSignature, publicKeyAndIdSignature, type) - } catch (e) { - err = e.toString() - } - assert.strictEqual(err, 'Error: Identity provider is required') - }) + // it('throws and error if identity provider was not given in constructor', async () => { + // let err + // try { + // identity = new Identity('abc', publicKey, idSignature, publicKeyAndIdSignature, type) + // } catch (e) { + // err = e.toString() + // } + // assert.strictEqual(err, 'Error: Identity provider is required') + // }) it('throws and error if identity type was not given in constructor', async () => { let err diff --git a/test/keyvalue.spec.js b/test/keyvalue.spec.js index 70e98a2..b8f4212 100644 --- a/test/keyvalue.spec.js +++ b/test/keyvalue.spec.js @@ -1,7 +1,7 @@ import { deepStrictEqual, strictEqual } from 'assert' import rimraf from 'rimraf' import { Log, Entry } from '../src/oplog/index.js' -import { IdentityProvider } from '../src/identities/index.js' +import { Identities } from '../src/identities/index.js' import KeyStore from '../src/key-store.js' import { KeyValue, KeyValuePersisted, Database } from '../src/db/index.js' import { IPFSBlockStorage, LevelStorage } from '../src/storage/index.js' @@ -13,7 +13,7 @@ import waitFor from './utils/wait-for.js' import { identityKeys, signingKeys, createTestIdentities, cleanUpTestIdentities } from './fixtures/orbit-db-identity-keys.js' const { sync: rmrf } = rimraf -const { createIdentity } = IdentityProvider +const { createIdentity } = Identities const OpLog = { Log, Entry, IPFSBlockStorage, LevelStorage } @@ -25,11 +25,19 @@ Object.keys(testAPIs).forEach((IPFS) => { let ipfs1, ipfs2 let keystore, signingKeyStore let peerId1, peerId2 + let identities1, identities2 let testIdentity1, testIdentity2 let kv1, kv2 const databaseId = 'kv-AAA' + const accessController = { + canAppend: async (entry) => { + const identity = await identities1.getIdentity(entry.identity) + return identity.id === testIdentity1.id + } + } + before(async () => { // Start two IPFS instances ipfsd1 = await startIpfs(IPFS, config.daemon1) @@ -43,7 +51,9 @@ Object.keys(testAPIs).forEach((IPFS) => { peerId1 = await getIpfsPeerId(ipfs1) peerId2 = await getIpfsPeerId(ipfs2) - const testIdentities = await createTestIdentities(ipfs1, ipfs2) + const [identities, testIdentities] = await createTestIdentities(ipfs1, ipfs2) + identities1 = identities[0] + identities2 = identities[1] testIdentity1 = testIdentities[0] testIdentity2 = testIdentities[1] @@ -52,7 +62,7 @@ Object.keys(testAPIs).forEach((IPFS) => { }) after(async () => { - await cleanUpTestIdentities([testIdentity1, testIdentity2]) + await cleanUpTestIdentities([identities1, identities2]) if (ipfsd1) { await stopIpfs(ipfsd1) @@ -94,13 +104,6 @@ Object.keys(testAPIs).forEach((IPFS) => { let updateCount = 0 // const syncCount = 0 - const accessController = { - canAppend: async (entry) => { - const identity = await testIdentity1.provider.get(entry.identity) - return identity.id === testIdentity1.id - } - } - const onUpdate = (entry) => { ++updateCount } @@ -223,13 +226,6 @@ Object.keys(testAPIs).forEach((IPFS) => { let updateCount = 0 // let syncCount = 0 - const accessController = { - canAppend: async (entry) => { - const identity = await testIdentity1.provider.get(entry.identity) - return identity.id === testIdentity1.id - } - } - const onUpdate = (entry) => { ++updateCount } diff --git a/test/oplog/append.test.js b/test/oplog/append.test.js index 7c59a69..bffe79d 100644 --- a/test/oplog/append.test.js +++ b/test/oplog/append.test.js @@ -3,13 +3,13 @@ import rimraf from 'rimraf' import { copy } from 'fs-extra' import { Log } from '../../src/oplog/index.js' import MemoryStorage from '../../src/storage/memory.js' -import { IdentityProvider } from '../../src/identities/index.js' +import { Identities } from '../../src/identities/index.js' import KeyStore from '../../src/key-store.js' // Test utils import { config, testAPIs } from 'orbit-db-test-utils' -const { createIdentity } = IdentityProvider +const { createIdentity } = Identities const { sync: rmrf } = rimraf let testIdentity @@ -21,6 +21,7 @@ Object.keys(testAPIs).forEach((IPFS) => { const { identityKeyFixtures, signingKeyFixtures, identityKeysPath, signingKeysPath } = config let keystore, signingKeyStore + let identities before(async () => { rmrf(identityKeysPath) @@ -30,9 +31,11 @@ Object.keys(testAPIs).forEach((IPFS) => { keystore = new KeyStore(identityKeysPath) signingKeyStore = new KeyStore(signingKeysPath) + const storage = await MemoryStorage() - testIdentity = await createIdentity({ id: 'userA', keystore, signingKeyStore, storage }) + identities = await Identities({ keystore, signingKeyStore, storage }) + testIdentity = await identities.createIdentity({ id: 'userA' }) }) after(async () => { diff --git a/test/oplog/crdt.test.js b/test/oplog/crdt.test.js index 6a9d1bb..74e589d 100644 --- a/test/oplog/crdt.test.js +++ b/test/oplog/crdt.test.js @@ -2,7 +2,7 @@ import { strictEqual, deepStrictEqual } from 'assert' import rimraf from 'rimraf' import { copy } from 'fs-extra' import { Log } from '../../src/oplog/index.js' -import { IdentityProvider } from '../../src/identities/index.js' +import { Identities } from '../../src/identities/index.js' import KeyStore from '../../src/key-store.js' import MemoryStorage from '../../src/storage/memory.js' @@ -10,7 +10,7 @@ import MemoryStorage from '../../src/storage/memory.js' import { config, testAPIs } from 'orbit-db-test-utils' const { sync: rmrf } = rimraf -const { createIdentity } = IdentityProvider +const { createIdentity } = Identities let testIdentity, testIdentity2, testIdentity3 @@ -21,6 +21,7 @@ Object.keys(testAPIs).forEach((IPFS) => { const { identityKeyFixtures, signingKeyFixtures, identityKeysPath, signingKeysPath } = config let keystore, signingKeyStore + let identities1, identities2, identities3 before(async () => { rmrf(identityKeysPath) @@ -30,11 +31,15 @@ Object.keys(testAPIs).forEach((IPFS) => { keystore = new KeyStore(identityKeysPath) signingKeyStore = new KeyStore(signingKeysPath) + const storage = await MemoryStorage() - testIdentity = await createIdentity({ id: 'userA', keystore, signingKeyStore, storage }) - testIdentity2 = await createIdentity({ id: 'userB', keystore, signingKeyStore, storage }) - testIdentity3 = await createIdentity({ id: 'userC', keystore, signingKeyStore, storage }) + identities1 = await Identities({ keystore, signingKeyStore, storage }) + identities2 = await Identities({ keystore, signingKeyStore, storage }) + identities3 = await Identities({ keystore, signingKeyStore, storage }) + testIdentity = await identities1.createIdentity({ id: 'userA' }) + testIdentity2 = await identities2.createIdentity({ id: 'userB' }) + testIdentity3 = await identities3.createIdentity({ id: 'userC' }) }) after(async () => { diff --git a/test/oplog/entry.test.js b/test/oplog/entry.test.js index 2356d87..38c5785 100644 --- a/test/oplog/entry.test.js +++ b/test/oplog/entry.test.js @@ -2,14 +2,14 @@ import { strictEqual, deepStrictEqual } from 'assert' import rimraf from 'rimraf' import { copy } from 'fs-extra' import { Entry } from '../../src/oplog/index.js' -import { IdentityProvider } from '../../src/identities/index.js' +import { Identities } from '../../src/identities/index.js' import KeyStore from '../../src/key-store.js' import { config, testAPIs, startIpfs, stopIpfs } from 'orbit-db-test-utils' // import IdentityStorage from '../src/identity-storage.js' // import IPFSBlockStorage from '../src/ipfs-block-storage.js' const { sync: rmrf } = rimraf -const { createIdentity } = IdentityProvider +const { createIdentity } = Identities const { create, isEntry } = Entry Object.keys(testAPIs).forEach((IPFS) => { @@ -18,8 +18,9 @@ Object.keys(testAPIs).forEach((IPFS) => { const { identityKeyFixtures, signingKeyFixtures, identityKeysPath, signingKeysPath } = config - let testIdentity let keystore, signingKeyStore, ipfsBlockStore, identityStore + let identities + let testIdentity let ipfsd, ipfs before(async () => { @@ -32,7 +33,8 @@ Object.keys(testAPIs).forEach((IPFS) => { keystore = new KeyStore(identityKeysPath) signingKeyStore = new KeyStore(signingKeysPath) - testIdentity = await createIdentity({ id: 'userA', keystore, signingKeyStore, ipfs }) + identities = await Identities({ keystore, signingKeyStore, ipfs }) + testIdentity = await identities.createIdentity({ id: 'userA' }) }) after(async () => { @@ -76,11 +78,11 @@ Object.keys(testAPIs).forEach((IPFS) => { // strictEqual(entry.hash, expectedHash) }) - it.skip('retrieves the identity from an entry', async() => { + it('retrieves the identity from an entry', async() => { const expected = testIdentity.toJSON() const payload = 'hello world' const entry = await create(testIdentity, 'A', payload) - const entryIdentity = await identityStore.get(entry.identity) + const entryIdentity = await identities.getIdentity(entry.identity) deepStrictEqual(entryIdentity, expected) }) diff --git a/test/oplog/heads.test.js b/test/oplog/heads.test.js index 179e643..2b4d050 100644 --- a/test/oplog/heads.test.js +++ b/test/oplog/heads.test.js @@ -2,7 +2,7 @@ import { strictEqual, deepStrictEqual } from 'assert' import rimraf from 'rimraf' import { copy } from 'fs-extra' import { Log } from '../../src/oplog/index.js' -import { IdentityProvider } from '../../src/identities/index.js' +import { Identities } from '../../src/identities/index.js' import KeyStore from '../../src/key-store.js' import MemoryStorage from '../../src/storage/memory.js' @@ -10,7 +10,7 @@ import MemoryStorage from '../../src/storage/memory.js' import { config, testAPIs } from 'orbit-db-test-utils' const { sync: rmrf } = rimraf -const { createIdentity } = IdentityProvider +const { createIdentity } = Identities let testIdentity @@ -25,6 +25,7 @@ Object.keys(testAPIs).forEach((IPFS) => { const { identityKeyFixtures, signingKeyFixtures, identityKeysPath, signingKeysPath } = config let keystore, signingKeyStore + let identities before(async () => { rmrf(identityKeysPath) @@ -36,7 +37,8 @@ Object.keys(testAPIs).forEach((IPFS) => { signingKeyStore = new KeyStore(signingKeysPath) const storage = await MemoryStorage() - testIdentity = await createIdentity({ id: 'userA', keystore, signingKeyStore, storage }) + identities = await Identities({ keystore, signingKeyStore, storage }) + testIdentity = await identities.createIdentity({ id: 'userA' }) }) after(async () => { diff --git a/test/oplog/iterator.test.js b/test/oplog/iterator.test.js index 9b8ce11..cf5d904 100644 --- a/test/oplog/iterator.test.js +++ b/test/oplog/iterator.test.js @@ -1,7 +1,7 @@ import { strictEqual, deepStrictEqual } from 'assert' import rimraf from 'rimraf' import { Log } from '../../src/oplog/index.js' -import { IdentityProvider } from '../../src/identities/index.js' +import { Identities } from '../../src/identities/index.js' import KeyStore from '../../src/key-store.js' import LogCreator from './utils/log-creator.js' import all from 'it-all' @@ -12,7 +12,7 @@ import { config, testAPIs, startIpfs, stopIpfs } from 'orbit-db-test-utils' import { identityKeys, signingKeys } from '../fixtures/orbit-db-identity-keys.js' const { sync: rmrf } = rimraf -const { createIdentity } = IdentityProvider +const { createIdentity } = Identities const { createLogWithSixteenEntries } = LogCreator Object.keys(testAPIs).forEach((IPFS) => { @@ -22,6 +22,7 @@ Object.keys(testAPIs).forEach((IPFS) => { let ipfs let ipfsd let keystore, signingKeyStore + let identities1, identities2, identities3 let testIdentity, testIdentity2, testIdentity3 before(async () => { @@ -39,9 +40,12 @@ Object.keys(testAPIs).forEach((IPFS) => { const storage = await MemoryStorage() - testIdentity = await createIdentity({ id: 'userA', keystore, signingKeyStore, storage }) - testIdentity2 = await createIdentity({ id: 'userB', keystore, signingKeyStore, storage }) - testIdentity3 = await createIdentity({ id: 'userC', keystore, signingKeyStore, storage }) + identities1 = await Identities({ keystore, signingKeyStore, storage }) + identities2 = await Identities({ keystore, signingKeyStore, storage }) + identities3 = await Identities({ keystore, signingKeyStore, storage }) + testIdentity = await identities1.createIdentity({ id: 'userA' }) + testIdentity2 = await identities2.createIdentity({ id: 'userB' }) + testIdentity3 = await identities3.createIdentity({ id: 'userC' }) ipfsd = await startIpfs(IPFS, config.defaultIpfsConfig) ipfs = ipfsd.api diff --git a/test/oplog/join-concurrent.test.js b/test/oplog/join-concurrent.test.js index 794707a..e873784 100644 --- a/test/oplog/join-concurrent.test.js +++ b/test/oplog/join-concurrent.test.js @@ -2,7 +2,7 @@ import { strictEqual, deepStrictEqual } from 'assert' import rimraf from 'rimraf' import { copy } from 'fs-extra' import { Log } from '../../src/oplog/index.js' -import { IdentityProvider } from '../../src/identities/index.js' +import { Identities } from '../../src/identities/index.js' import KeyStore from '../../src/key-store.js' import MemoryStorage from '../../src/storage/memory.js' @@ -10,7 +10,7 @@ import MemoryStorage from '../../src/storage/memory.js' import { config, testAPIs } from 'orbit-db-test-utils' const { sync: rmrf } = rimraf -const { createIdentity } = IdentityProvider +const { createIdentity } = Identities let testIdentity, testIdentity2 @@ -21,6 +21,7 @@ Object.keys(testAPIs).forEach(IPFS => { const { identityKeyFixtures, signingKeyFixtures, identityKeysPath, signingKeysPath } = config let keystore, signingKeyStore + let identities1, identities2 before(async () => { rmrf(identityKeysPath) @@ -33,8 +34,10 @@ Object.keys(testAPIs).forEach(IPFS => { const storage = await MemoryStorage() - testIdentity = await createIdentity({ id: 'userA', keystore, signingKeyStore, storage }) - testIdentity2 = await createIdentity({ id: 'userB', keystore, signingKeyStore, storage }) + identities1 = await Identities({ keystore, signingKeyStore, storage }) + identities2 = await Identities({ keystore, signingKeyStore, storage }) + testIdentity = await identities1.createIdentity({ id: 'userA' }) + testIdentity2 = await identities2.createIdentity({ id: 'userB' }) }) after(async () => { diff --git a/test/oplog/join.test.js b/test/oplog/join.test.js index 43bfc15..9f20aba 100644 --- a/test/oplog/join.test.js +++ b/test/oplog/join.test.js @@ -1,7 +1,7 @@ import { strictEqual, notStrictEqual, deepStrictEqual } from 'assert' import rimraf from 'rimraf' import { Log, Clock } from '../../src/oplog/index.js' -import { IdentityProvider } from '../../src/identities/index.js' +import { Identities } from '../../src/identities/index.js' import KeyStore from '../../src/key-store.js' import MemoryStorage from '../../src/storage/memory.js' @@ -10,7 +10,7 @@ import { config, testAPIs } from 'orbit-db-test-utils' import { identityKeys, signingKeys } from '../fixtures/orbit-db-identity-keys.js' const { sync: rmrf } = rimraf -const { createIdentity } = IdentityProvider +const { createIdentity } = Identities const last = (arr) => { return arr[arr.length - 1] @@ -22,6 +22,7 @@ Object.keys(testAPIs).forEach((IPFS) => { let keystore, signingKeyStore let log1, log2, log3, log4 + let identities1, identities2, identities3, identities4 let testIdentity, testIdentity2, testIdentity3, testIdentity4 before(async () => { @@ -39,10 +40,14 @@ Object.keys(testAPIs).forEach((IPFS) => { const storage = await MemoryStorage() - testIdentity = await createIdentity({ id: 'userC', keystore, signingKeyStore, storage }) - testIdentity2 = await createIdentity({ id: 'userB', keystore, signingKeyStore, storage }) - testIdentity3 = await createIdentity({ id: 'userD', keystore, signingKeyStore, storage }) - testIdentity4 = await createIdentity({ id: 'userA', keystore, signingKeyStore, storage }) + identities1 = await Identities({ keystore, signingKeyStore, storage }) + identities2 = await Identities({ keystore, signingKeyStore, storage }) + identities3 = await Identities({ keystore, signingKeyStore, storage }) + identities4 = await Identities({ keystore, signingKeyStore, storage }) + testIdentity = await identities1.createIdentity({ id: 'userC' }) + testIdentity2 = await identities2.createIdentity({ id: 'userB' }) + testIdentity3 = await identities3.createIdentity({ id: 'userD' }) + testIdentity4 = await identities4.createIdentity({ id: 'userA' }) }) after(async () => { diff --git a/test/oplog/load.test.js b/test/oplog/load.test.js index 3d850a0..52f5ce0 100644 --- a/test/oplog/load.test.js +++ b/test/oplog/load.test.js @@ -3,7 +3,7 @@ import rimraf from 'rimraf' import { copy } from 'fs-extra' import { Log, Entry, Sorting } from '../../src/oplog/index.js' import bigLogString from '../fixtures/big-log.fixture.js' -import { IdentityProvider } from '../../src/identities/index.js' +import { Identities } from '../../src/identities/index.js' import KeyStore from '../../src/key-store.js' import LogCreator from './utils/log-creator.js' import MemoryStorage from '../../src/storage/memory.js' @@ -13,7 +13,7 @@ import { config, MemStore, testAPIs, startIpfs, stopIpfs } from 'orbit-db-test-u const { sync: rmrf } = rimraf const { LastWriteWins } = Sorting -const { createIdentity } = IdentityProvider +const { createIdentity } = Identities const { fromJSON, fromEntryHash, fromEntry, fromMultihash: _fromMultihash } = Log const { fromMultihash, create, compare } = Entry const { createLogWithSixteenEntries, createLogWithTwoHundredEntries } = LogCreator diff --git a/test/oplog/log.test.js b/test/oplog/log.test.js index 928b148..8d10978 100644 --- a/test/oplog/log.test.js +++ b/test/oplog/log.test.js @@ -1,7 +1,7 @@ import { notStrictEqual, deepStrictEqual, strictEqual } from 'assert' import rimraf from 'rimraf' import { Log, Entry } from '../../src/oplog/index.js' -import { IdentityProvider } from '../../src/identities/index.js' +import { Identities } from '../../src/identities/index.js' import KeyStore from '../../src/key-store.js' import { copy } from 'fs-extra' import MemoryStorage from '../../src/storage/memory.js' @@ -11,7 +11,7 @@ import { config, testAPIs } from 'orbit-db-test-utils' const { sync: rmrf } = rimraf const { create } = Entry -const { createIdentity } = IdentityProvider +const { createIdentity } = Identities let testIdentity @@ -22,6 +22,7 @@ Object.keys(testAPIs).forEach((IPFS) => { const { identityKeyFixtures, signingKeyFixtures, identityKeysPath, signingKeysPath } = config let keystore, signingKeyStore + let identities before(async () => { await copy(identityKeyFixtures, identityKeysPath) @@ -32,7 +33,8 @@ Object.keys(testAPIs).forEach((IPFS) => { const storage = await MemoryStorage() - testIdentity = await createIdentity({ id: 'userA', keystore, signingKeyStore, storage }) + identities = await Identities({ keystore, signingKeyStore, storage }) + testIdentity = await identities.createIdentity({ id: 'userA' }) }) after(async () => { diff --git a/test/oplog/references.test.js b/test/oplog/references.test.js index 2851e3a..3e028ca 100644 --- a/test/oplog/references.test.js +++ b/test/oplog/references.test.js @@ -2,7 +2,7 @@ import { strictEqual } from 'assert' import rimraf from 'rimraf' import { copy } from 'fs-extra' import { Log } from '../../src/oplog/index.js' -import { IdentityProvider } from '../../src/identities/index.js' +import { Identities } from '../../src/identities/index.js' import KeyStore from '../../src/key-store.js' import MemoryStorage from '../../src/storage/memory.js' @@ -10,7 +10,7 @@ import MemoryStorage from '../../src/storage/memory.js' import { config, testAPIs } from 'orbit-db-test-utils' const { sync: rmrf } = rimraf -const { createIdentity } = IdentityProvider +const { createIdentity } = Identities let testIdentity @@ -21,6 +21,7 @@ Object.keys(testAPIs).forEach((IPFS) => { const { identityKeyFixtures, signingKeyFixtures, identityKeysPath, signingKeysPath } = config let keystore, signingKeyStore + let identities before(async () => { rmrf(identityKeysPath) @@ -33,7 +34,8 @@ Object.keys(testAPIs).forEach((IPFS) => { const storage = await MemoryStorage() - testIdentity = await createIdentity({ id: 'userA', keystore, signingKeyStore, storage }) + identities = await Identities({ keystore, signingKeyStore, storage }) + testIdentity = await identities.createIdentity({ id: 'userA' }) }) after(async () => { diff --git a/test/oplog/replicate.test.js b/test/oplog/replicate.test.js index d28ed5f..3409fb2 100644 --- a/test/oplog/replicate.test.js +++ b/test/oplog/replicate.test.js @@ -3,24 +3,29 @@ import rimraf from 'rimraf' import { copy } from 'fs-extra' import { Log, Entry } from '../../src/index.js' import { MemoryStorage, IPFSBlockStorage } from '../../src/storage/index.js' -import { IdentityProvider } from '../../src/identities/index.js' +import { Identities } from '../../src/identities/index.js' import KeyStore from '../../src/key-store.js' // Test utils import { config, testAPIs, startIpfs, stopIpfs, getIpfsPeerId, waitForPeers, connectPeers } from 'orbit-db-test-utils' +import { createTestIdentities, cleanUpTestIdentities } from '../fixtures/orbit-db-identity-keys.js' const { sync: rmrf } = rimraf -const { createIdentity } = IdentityProvider +const { createIdentity } = Identities Object.keys(testAPIs).forEach((IPFS) => { describe('ipfs-log - Replication (' + IPFS + ')', function () { this.timeout(config.timeout * 2) - let ipfsd1, ipfsd2, ipfs1, ipfs2, id1, id2, testIdentity, testIdentity2 - const { identityKeyFixtures, signingKeyFixtures, identityKeysPath, signingKeysPath } = config + let ipfsd1, ipfsd2 + let ipfs1, ipfs2 + let id1, id2 + let keystore, signingKeyStore + let identities1, identities2 + let testIdentity1, testIdentity2 let storage1, storage2 before(async () => { @@ -41,27 +46,22 @@ Object.keys(testAPIs).forEach((IPFS) => { id1 = await getIpfsPeerId(ipfs1) id2 = await getIpfsPeerId(ipfs2) - keystore = new KeyStore(identityKeysPath) - signingKeyStore = new KeyStore(signingKeysPath) - - const storage = await MemoryStorage() - - // Create an identity for each peers - testIdentity = await createIdentity({ id: 'userB', keystore, signingKeyStore, storage }) - testIdentity2 = await createIdentity({ id: 'userA', keystore, signingKeyStore, storage }) + const [identities, testIdentities] = await createTestIdentities(ipfs1, ipfs2) + identities1 = identities[0] + identities2 = identities[1] + testIdentity2 = testIdentities[0] + testIdentity1 = testIdentities[1] storage1 = await IPFSBlockStorage({ ipfs: ipfs1 }) storage2 = await IPFSBlockStorage({ ipfs: ipfs2 }) }) after(async () => { + await cleanUpTestIdentities([identities1, identities2]) await stopIpfs(ipfsd1) await stopIpfs(ipfsd2) - rmrf(identityKeysPath) - rmrf(signingKeysPath) - - await keystore.close() - await signingKeyStore.close() + await storage1.close() + await storage2.close() }) describe('replicates logs deterministically', async function () { @@ -99,9 +99,9 @@ Object.keys(testAPIs).forEach((IPFS) => { } beforeEach(async () => { - log1 = await Log(testIdentity, { logId, storage: storage1 }) + log1 = await Log(testIdentity1, { logId, storage: storage1 }) log2 = await Log(testIdentity2, { logId, storage: storage2 }) - input1 = await Log(testIdentity, { logId, storage: storage1 }) + input1 = await Log(testIdentity1, { logId, storage: storage1 }) input2 = await Log(testIdentity2, { logId, storage: storage2 }) await ipfs1.pubsub.subscribe(logId, handleMessage1) await ipfs2.pubsub.subscribe(logId, handleMessage2) @@ -143,7 +143,7 @@ Object.keys(testAPIs).forEach((IPFS) => { await whileProcessingMessages(config.timeout) - const result = await Log(testIdentity, { logId, storage: storage1 }) + const result = await Log(testIdentity1, { logId, storage: storage1 }) await result.join(log1) await result.join(log2) diff --git a/test/oplog/signed-log.test.js b/test/oplog/signed-log.test.js index a69654d..8803203 100644 --- a/test/oplog/signed-log.test.js +++ b/test/oplog/signed-log.test.js @@ -1,40 +1,32 @@ import { notStrictEqual, strictEqual, deepStrictEqual } from 'assert' import rimraf from 'rimraf' import { Log } from '../../src/oplog/index.js' -import { IdentityProvider } from '../../src/identities/index.js' -import KeyStore from '../../src/key-store.js' +import { Identities } from '../../src/identities/index.js' // Test utils import { config, testAPIs } from 'orbit-db-test-utils' import { identityKeys, signingKeys, createTestIdentities, cleanUpTestIdentities } from '../fixtures/orbit-db-identity-keys.js' const { sync: rmrf } = rimraf -const { createIdentity } = IdentityProvider +const { createIdentity } = Identities Object.keys(testAPIs).forEach((IPFS) => { describe('Signed Log (' + IPFS + ')', function () { this.timeout(config.timeout) - let keystore, signingKeyStore + let identities1, identities2 let testIdentity, testIdentity2 before(async () => { - const testIdentities = await createTestIdentities() + const [identities, testIdentities] = await createTestIdentities() + identities1 = identities[0] + identities2 = identities[1] testIdentity = testIdentities[0] testIdentity2 = testIdentities[1] }) after(async () => { - await cleanUpTestIdentities([testIdentity, testIdentity2]) - - if (keystore) { - await keystore.close() - } - if (signingKeyStore) { - await signingKeyStore.close() - } - rmrf('./keys_1') - rmrf('./keys_2') + await cleanUpTestIdentities([identities1, identities2]) }) it('creates a signed log', async () => { @@ -160,7 +152,7 @@ Object.keys(testAPIs).forEach((IPFS) => { it('throws an error upon join if entry doesn\'t have append access', async () => { const testACL = { canAppend: async (entry) => { - const identity = await testIdentity.provider.get(entry.identity) + const identity = await identities1.getIdentity(entry.identity) return identity && identity.id !== testIdentity2.id } } diff --git a/test/storage.spec.js b/test/storage.spec.js index bb163b4..326701c 100644 --- a/test/storage.spec.js +++ b/test/storage.spec.js @@ -2,7 +2,7 @@ import * as IPFS from 'ipfs' import { strictEqual, notStrictEqual } from 'assert' import rimraf from 'rimraf' import { Log } from '../src/oplog/index.js' -import { IdentityProvider } from '../src/identities/index.js' +import { Identities } from '../src/identities/index.js' import KeyStore from '../src/key-store.js' import { IPFSBlockStorage, MemoryStorage, LRUStorage, ComposedStorage } from '../src/storage/index.js' import { copy } from 'fs-extra' @@ -11,7 +11,7 @@ import { copy } from 'fs-extra' import { config, testAPIs } from 'orbit-db-test-utils' const { sync: rmrf } = rimraf -const { createIdentity } = IdentityProvider +const { createIdentity } = Identities Object.keys(testAPIs).forEach((_) => { describe('Storages (' + _ + ')', function () { @@ -39,8 +39,8 @@ Object.keys(testAPIs).forEach((_) => { signingKeyStore = new KeyStore(signingKeysPath) const storage = await MemoryStorage() - - testIdentity1 = await createIdentity({ id: 'userA', keystore, signingKeyStore, storage }) + const identities = await Identities({ keystore, signingKeyStore, storage }) + testIdentity1 = await identities.createIdentity({ id: 'userA' }) }) after(async () => { From 4b4d2ff35c036e278e4bb88fe2e5f7e870e1c353 Mon Sep 17 00:00:00 2001 From: haad Date: Fri, 17 Feb 2023 11:12:32 +0200 Subject: [PATCH 2/6] Refactor Identity --- src/identities/identities.js | 101 +++++----- src/identities/identity-store.js | 38 ---- src/identities/identity.js | 184 +++++++++--------- src/identities/index.js | 8 +- src/oplog/entry.js | 8 +- test/identies/fixtures/keys/000005.ldb | Bin 459 -> 0 bytes test/identies/fixtures/keys/000032.log | 0 test/identies/fixtures/keys/CURRENT | 1 - test/identies/fixtures/keys/LOCK | 0 test/identies/fixtures/keys/LOG | 3 - test/identies/fixtures/keys/LOG.old | 3 - test/identies/fixtures/keys/MANIFEST-000031 | Bin 185 -> 0 bytes test/identities/did-identity-provider.spec.js | 24 ++- .../ethereum-identity-provider.spec.js | 22 ++- test/identities/identity-provider.spec.js | 19 +- test/identities/identity.spec.js | 30 +-- test/oplog/entry.test.js | 11 +- 17 files changed, 231 insertions(+), 221 deletions(-) delete mode 100644 src/identities/identity-store.js delete mode 100644 test/identies/fixtures/keys/000005.ldb delete mode 100644 test/identies/fixtures/keys/000032.log delete mode 100644 test/identies/fixtures/keys/CURRENT delete mode 100644 test/identies/fixtures/keys/LOCK delete mode 100644 test/identies/fixtures/keys/LOG delete mode 100644 test/identies/fixtures/keys/LOG.old delete mode 100644 test/identies/fixtures/keys/MANIFEST-000031 diff --git a/src/identities/identities.js b/src/identities/identities.js index c7f27a6..8559fbd 100644 --- a/src/identities/identities.js +++ b/src/identities/identities.js @@ -1,10 +1,9 @@ -import Identity from './identity.js' +import Identity, { isIdentity, isEqual, decodeIdentity } from './identity.js' import OrbitDBIdentityProvider from './providers/orbitdb.js' // import DIDIdentityProvider from './identity-providers/did.js' // import EthIdentityProvider from './identity-providers/ethereum.js' import KeyStore from '../key-store.js' -import IdentityStore from './identity-store.js' -import { LRUStorage } from '../storage/index.js' +import { LRUStorage, IPFSBlockStorage, MemoryStorage } from '../storage/index.js' import path from 'path' const DefaultProviderType = 'orbitdb' @@ -16,15 +15,18 @@ const supportedTypes = { // [EthIdentityProvider.type]: EthIdentityProvider } -const Identities = async ({ keystore, signingKeyStore, identityKeysPath, signingKeysPath, identityStore, ipfs } = {}) => { +const Identities = async ({ keystore, signingKeyStore, identityKeysPath, signingKeysPath, storage, ipfs } = {}) => { keystore = keystore || new KeyStore(identityKeysPath || DefaultIdentityKeysPath) signingKeyStore = signingKeyStore || (signingKeysPath ? new KeyStore(signingKeysPath) : keystore) - identityStore = identityStore || await IdentityStore({ ipfs }) + storage = storage || (ipfs ? await IPFSBlockStorage({ ipfs, pin: true }) : await MemoryStorage()) const verifiedIdentitiesCache = await LRUStorage({ size: 1000 }) const getIdentity = async (hash) => { - return identityStore.get(hash) + const bytes = await storage.get(hash) + if (bytes) { + return decodeIdentity(bytes) + } } const createIdentity = async (options = {}) => { @@ -38,18 +40,21 @@ const Identities = async ({ keystore, signingKeyStore, identityKeysPath, signing const privateKey = await keystore.getKey(id) || await keystore.createKey(id) const publicKey = keystore.getPublic(privateKey) const idSignature = await KeyStore.sign(privateKey, id) - const pubKeyIdSignature = await identityProvider.signIdentity(publicKey + idSignature, options) - const identity = new Identity(id, publicKey, idSignature, pubKeyIdSignature, type, sign, verify) + const publicKeyAndIdSignature = await identityProvider.signIdentity(publicKey + idSignature, options) + const identity = await Identity({ id, publicKey, idSignature, publicKeyAndIdSignature, type, sign, verify }) - const hash = await identityStore.put(identity.toJSON()) - // TODO: fix this monkey patching - identity.hash = hash + // const { hash, bytes } = await encodeIdentity(identity) + // console.log(hash, bytes) + await storage.put(identity.hash, identity.bytes) + // const hash = await storage.put(identity.toJSON()) + // // TODO: fix this monkey patching + // identity.hash = hash return identity } const verifyIdentity = async (identity) => { - if (!Identity.isIdentity(identity)) { + if (!isIdentity(identity)) { return false } @@ -62,14 +67,14 @@ const Identities = async ({ keystore, signingKeyStore, identityKeysPath, signing const verifiedIdentity = await verifiedIdentitiesCache.get(signatures.id) if (verifiedIdentity) { - return Identity.isEqual(identity, verifiedIdentity) + return isEqual(identity, verifiedIdentity) } const Provider = getProviderFor(identity.type) const identityVerified = await Provider.verifyIdentity(identity) if (identityVerified) { - await verifiedIdentitiesCache.put(signatures.id, identity.toJSON()) + await verifiedIdentitiesCache.put(signatures.id, identity) } return identityVerified @@ -89,47 +94,49 @@ const Identities = async ({ keystore, signingKeyStore, identityKeysPath, signing return KeyStore.verify(signature, publicKey, data) } - const isSupported = (type) => { - return Object.keys(supportedTypes).includes(type) - } - - const getProviderFor = (type) => { - if (!isSupported(type)) { - throw new Error(`IdentityProvider type '${type}' is not supported`) - } - - return supportedTypes[type] - } - - const addIdentityProvider = (IdentityProvider) => { - if (!IdentityProvider) { - throw new Error('IdentityProvider must be given as an argument') - } - - if (!IdentityProvider.type || - typeof IdentityProvider.type !== 'string') { - throw new Error('Given IdentityProvider doesn\'t have a field \'type\'') - } - - supportedTypes[IdentityProvider.type] = IdentityProvider - } - - const removeIdentityProvider = (type) => { - delete supportedTypes[type] - } - return { createIdentity, verifyIdentity, getIdentity, sign, verify, - isSupported, - addIdentityProvider, - removeIdentityProvider, keystore, signingKeyStore } } -export { Identities as default } +const isProviderSupported = (type) => { + return Object.keys(supportedTypes).includes(type) +} + +const getProviderFor = (type) => { + if (!isProviderSupported(type)) { + throw new Error(`IdentityProvider type '${type}' is not supported`) + } + + return supportedTypes[type] +} + +const addIdentityProvider = (IdentityProvider) => { + if (!IdentityProvider) { + throw new Error('IdentityProvider must be given as an argument') + } + + if (!IdentityProvider.type || + typeof IdentityProvider.type !== 'string') { + throw new Error('Given IdentityProvider doesn\'t have a field \'type\'') + } + + supportedTypes[IdentityProvider.type] = IdentityProvider +} + +const removeIdentityProvider = (type) => { + delete supportedTypes[type] +} + +export { + Identities as default, + isProviderSupported, + addIdentityProvider, + removeIdentityProvider +} diff --git a/src/identities/identity-store.js b/src/identities/identity-store.js deleted file mode 100644 index 052638c..0000000 --- a/src/identities/identity-store.js +++ /dev/null @@ -1,38 +0,0 @@ -import IPFSBlockStorage from '../storage/ipfs-block.js' -import MemoryStorage from '../storage/memory.js' -import * as dagCbor from '@ipld/dag-cbor' -import { sha256 } from 'multiformats/hashes/sha2' -import { base58btc } from 'multiformats/bases/base58' -import * as Block from 'multiformats/block' - -const codec = dagCbor -const hasher = sha256 - -const IdentityStore = async ({ ipfs, storage } = {}) => { - storage = storage || (ipfs - ? await IPFSBlockStorage({ ipfs, pin: true }) - : await MemoryStorage()) - - const put = async (value) => { - const { cid, bytes } = await Block.encode({ value, codec, hasher }) - const hash = cid.toString(base58btc) - await storage.put(hash, bytes) - return hash - } - - const get = async (hash) => { - const bytes = await storage.get(hash) - - if (bytes) { - const { value } = await Block.decode({ bytes, codec, hasher }) - return value - } - } - - return { - put, - get - } -} - -export default IdentityStore diff --git a/src/identities/identity.js b/src/identities/identity.js index a70408c..c11e22f 100644 --- a/src/identities/identity.js +++ b/src/identities/identity.js @@ -1,98 +1,96 @@ +import * as Block from 'multiformats/block' +import * as dagCbor from '@ipld/dag-cbor' +import { sha256 } from 'multiformats/hashes/sha2' +import { base58btc } from 'multiformats/bases/base58' import isDefined from '../utils/is-defined.js' -class Identity { - constructor (id, publicKey, idSignature, pubKeyIdSignature, type, signFn, verifyFn) { - if (!isDefined(id)) { - throw new Error('Identity id is required') - } +const codec = dagCbor +const hasher = sha256 +const hashStringEncoding = base58btc - if (!isDefined(publicKey)) { - throw new Error('Invalid public key') - } - - if (!isDefined(idSignature)) { - throw new Error('Signature of the id (idSignature) is required') - } - - if (!isDefined(pubKeyIdSignature)) { - throw new Error('Signature of (publicKey + idSignature) is required') - } - - if (!isDefined(type)) { - throw new Error('Identity type is required') - } - - // if (!isDefined(provider)) { - // throw new Error('Identity provider is required') - // } - - this._id = id - this._publicKey = publicKey - this._signatures = Object.assign({}, { id: idSignature }, { publicKey: pubKeyIdSignature }) - this._type = type - // this._provider = provider - this.hash = null - this.sign = signFn - this.verify = verifyFn - } - - /** - * This is only used as a fallback to the clock id when necessary - * @return {string} public key hex encoded - */ - get id () { - return this._id - } - - get publicKey () { - return this._publicKey - } - - get signatures () { - return this._signatures - } - - get type () { - return this._type - } - - // get provider () { - // return this._provider - // } - - toJSON () { - return { - id: this.id, - publicKey: this.publicKey, - signatures: this.signatures, - type: this.type - } - } - - static isEqual (a, b) { - return a.id === b.id && - a.publicKey === b.publicKey && - a.signatures.id === b.signatures.id && - a.signatures.publicKey === b.signatures.publicKey - } - - static isIdentity (identity) { - return identity.id !== undefined && - identity.publicKey !== undefined && - identity.signatures !== undefined && - identity.signatures.id !== undefined && - identity.signatures.publicKey !== undefined && - identity.type !== undefined - } - - static toJSON (identity) { - return { - id: identity.id, - publicKey: identity.publicKey, - signatures: identity.signatures, - type: identity.type - } - } +const isEqual = (a, b) => { + return a.id === b.id && + a.publicKey === b.publicKey && + a.signatures.id === b.signatures.id && + a.signatures.publicKey === b.signatures.publicKey } -export default Identity +const isIdentity = (identity) => { + return isDefined(identity.id) && + isDefined(identity.publicKey) && + isDefined(identity.signatures) && + isDefined(identity.signatures.id) && + isDefined(identity.signatures.publicKey) && + isDefined(identity.type) +} + +/** + * Encode an Identity to a serializable form + * @param {Identity} identity Identity to encode + * @returns {Object} Object with fields hash and bytes + */ +const encodeIdentity = async (identity) => { + const { id, publicKey, signatures, type } = identity + const value = { id, publicKey, signatures, type } + const { cid, bytes } = await Block.encode({ value, codec, hasher }) + const hash = cid.toString(hashStringEncoding) + return { hash, bytes } +} + +/** + * Decode an Identity from bytes + * @param {Uint8Array} bytes Bytes from which to decode an Identity from + * @returns {Identity} + */ +const decodeIdentity = async (bytes) => { + const { value } = await Block.decode({ bytes, codec, hasher }) + const { id, publicKey, signatures, type } = value + return Identity({ + id, + publicKey, + idSignature: signatures.id, + publicKeyAndIdSignature: signatures.publicKey, + type + }) +} + +const Identity = async ({ id, publicKey, idSignature, publicKeyAndIdSignature, type, sign, verify } = {}) => { + if (!isDefined(id)) { + throw new Error('Identity id is required') + } + + if (!isDefined(publicKey)) { + throw new Error('Invalid public key') + } + + if (!isDefined(idSignature)) { + throw new Error('Signature of the id (idSignature) is required') + } + + if (!isDefined(publicKeyAndIdSignature)) { + throw new Error('Signature of (publicKey + idSignature) is required') + } + + if (!isDefined(type)) { + throw new Error('Identity type is required') + } + + const signatures = Object.assign({}, { id: idSignature }, { publicKey: publicKeyAndIdSignature }) + + const identity = { + id, + publicKey, + signatures, + type, + sign, + verify + } + + const { hash, bytes } = await encodeIdentity(identity) + identity.hash = hash + identity.bytes = bytes + + return identity +} + +export { Identity as default, isEqual, isIdentity, encodeIdentity, decodeIdentity } diff --git a/src/identities/index.js b/src/identities/index.js index 2a17e62..c24f0bb 100644 --- a/src/identities/index.js +++ b/src/identities/index.js @@ -1,2 +1,8 @@ -export { default as Identities } from './identities.js' +export { + default as Identities, + addIdentityProvider, + removeIdentityProvider, + isProviderSupported +} from './identities.js' + export { default as Identity } from './identity.js' diff --git a/src/oplog/entry.js b/src/oplog/entry.js index 51c4a01..8616303 100644 --- a/src/oplog/entry.js +++ b/src/oplog/entry.js @@ -58,12 +58,12 @@ const create = async (identity, id, payload, clock = null, next = [], refs = []) /** * Verifies an entry signature. * - * @param {IdentityProvider} identityProvider The identity provider to use + * @param {Identities} identities Identities system to use * @param {Entry} entry The entry being verified * @return {Promise} A promise that resolves to a boolean value indicating if the signature is valid */ -const verify = async (identityProvider, entry) => { - if (!identityProvider) throw new Error('Identity-provider is required, cannot verify entry') +const verify = async (identities, entry) => { + if (!identities) throw new Error('Identities is required, cannot verify entry') if (!isEntry(entry)) throw new Error('Invalid Log entry') if (!entry.key) throw new Error("Entry doesn't have a key") if (!entry.sig) throw new Error("Entry doesn't have a signature") @@ -79,7 +79,7 @@ const verify = async (identityProvider, entry) => { const { bytes } = await Block.encode({ value, codec, hasher }) - return identityProvider.verify(entry.sig, entry.key, bytes) + return identities.verify(entry.sig, entry.key, bytes) } /** diff --git a/test/identies/fixtures/keys/000005.ldb b/test/identies/fixtures/keys/000005.ldb deleted file mode 100644 index 4895d76b4de16f1dd98047e6bada4bb74832eac0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 459 zcmaJ+Jxd%>6rEW`5F2A-mttZW%3u-5-w0@CS4f!yr?}^EF6U%hzw=nd{wZJeKj}B84X2Nimd^WP(z2@X~35h^V9>GFYN=ESQXpT_!qJ z0z2W^*aV&efi7Mb7gw{bEYFu_>T<`G?D66@WW_?N>IpZSHBY&Yesj=vcQqQ+ z=jUfTa|^%r)@G^sub+2c9<${I&Yzx<-S_@^-bjx!q`YAN~Sz C`*_6w diff --git a/test/identies/fixtures/keys/000032.log b/test/identies/fixtures/keys/000032.log deleted file mode 100644 index e69de29..0000000 diff --git a/test/identies/fixtures/keys/CURRENT b/test/identies/fixtures/keys/CURRENT deleted file mode 100644 index d95f027..0000000 --- a/test/identies/fixtures/keys/CURRENT +++ /dev/null @@ -1 +0,0 @@ -MANIFEST-000031 diff --git a/test/identies/fixtures/keys/LOCK b/test/identies/fixtures/keys/LOCK deleted file mode 100644 index e69de29..0000000 diff --git a/test/identies/fixtures/keys/LOG b/test/identies/fixtures/keys/LOG deleted file mode 100644 index 0d9cafb..0000000 --- a/test/identies/fixtures/keys/LOG +++ /dev/null @@ -1,3 +0,0 @@ -2023/02/16-14:47:21.736625 171233000 Recovering log #30 -2023/02/16-14:47:21.737020 171233000 Delete type=3 #29 -2023/02/16-14:47:21.737069 171233000 Delete type=0 #30 diff --git a/test/identies/fixtures/keys/LOG.old b/test/identies/fixtures/keys/LOG.old deleted file mode 100644 index c178010..0000000 --- a/test/identies/fixtures/keys/LOG.old +++ /dev/null @@ -1,3 +0,0 @@ -2023/02/16-14:46:59.857680 16e03b000 Recovering log #28 -2023/02/16-14:46:59.858826 16e03b000 Delete type=0 #28 -2023/02/16-14:46:59.858852 16e03b000 Delete type=3 #27 diff --git a/test/identies/fixtures/keys/MANIFEST-000031 b/test/identies/fixtures/keys/MANIFEST-000031 deleted file mode 100644 index fd12011fd736412d1e08810fc6abe8f5fe9da500..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 185 zcmcDyxa-DZ21Z7yoYb<^oRlOzr^=Gl^338?=ltA)#G=HK{33P+*3--mDVZr&*{PLQ zRc5}~1$iM} { keystore = new KeyStore(keypath) await keystore.open() - identities = await Identities({ keystore }) DIDIdentityProvider.setDIDResolver(KeyDidResolver.getResolver()) - identities.addIdentityProvider(DIDIdentityProvider) + addIdentityProvider(DIDIdentityProvider) + identities = await Identities({ keystore }) }) after(async () => { @@ -82,7 +82,14 @@ describe('DID Identity Provider', function () { }) it('DID identity with incorrect id does not verify', async () => { - const identity2 = new Identity('NotAnId', identity.publicKey, identity.signatures.id, identity.signatures.publicKey, identity.type, identity.provider) + const { publicKey, signatures, type } = identity + const identity2 = await Identity({ + id: 'NotAnId', + publicKey, + idSignature: signatures.id, + publicKeyAndIdSignature: signatures.publicKey, + type + }) const verified = await identities.verifyIdentity(identity2) assert.strictEqual(verified, false) }) @@ -106,7 +113,14 @@ describe('DID Identity Provider', function () { it('throws an error if private key is not found from keystore', async () => { // Remove the key from the keystore (we're using a mock storage in these tests) - const modifiedIdentity = new Identity('this id does not exist', identity.publicKey, '', identity.signatures, identity.type, identity.provider) + const { publicKey, signatures, type } = identity + const modifiedIdentity = await Identity({ + id: 'this id does not exist', + publicKey, + idSignature: '', + publicKeyAndIdSignature: signatures.publicKey, + type + }) let signature let err try { diff --git a/test/identities/ethereum-identity-provider.spec.js b/test/identities/ethereum-identity-provider.spec.js index e055344..5530f75 100644 --- a/test/identities/ethereum-identity-provider.spec.js +++ b/test/identities/ethereum-identity-provider.spec.js @@ -2,7 +2,7 @@ import assert from 'assert' import path from 'path' import rmrf from 'rimraf' import { KeyStore, Identities } from '../../src/index.js' -import { Identity } from '../../src/identities/index.js' +import { Identity, addIdentityProvider } from '../../src/identities/index.js' import EthIdentityProvider from '../../src/identities/providers/ethereum.js' const keypath = path.resolve('./test/identities/fixtures/keys') @@ -15,8 +15,8 @@ describe('Ethereum Identity Provider', function () { before(async () => { keystore = new KeyStore(keypath) await keystore.open() + addIdentityProvider(EthIdentityProvider) identities = await Identities({ keystore }) - identities.addIdentityProvider(EthIdentityProvider) }) after(async () => { @@ -79,7 +79,14 @@ describe('Ethereum Identity Provider', function () { }) it('ethereum identity with incorrect id does not verify', async () => { - const identity2 = new Identity('NotAnId', identity.publicKey, identity.signatures.id, identity.signatures.publicKey, identity.type, identity.provider) + const { publicKey, signatures, type } = identity + const identity2 = await Identity({ + id: 'NotAnId', + publicKey, + idSignature: signatures.id, + publicKeyAndIdSignature: signatures.publicKey, + type + }) const verified = await identities.verifyIdentity(identity2) assert.strictEqual(verified, false) }) @@ -102,7 +109,14 @@ describe('Ethereum Identity Provider', function () { it('throws an error if private key is not found from keystore', async () => { // Remove the key from the keystore (we're using a mock storage in these tests) - const modifiedIdentity = new Identity('this id does not exist', identity.publicKey, '', identity.signatures, identity.type, identity.provider) + const { publicKey, signatures, type } = identity + const modifiedIdentity = await Identity({ + id: 'this id does not exist', + publicKey, + idSignature: '', + publicKeyAndIdSignature: signatures.publicKey, + type + }) let signature let err try { diff --git a/test/identities/identity-provider.spec.js b/test/identities/identity-provider.spec.js index 19805a2..4aca241 100644 --- a/test/identities/identity-provider.spec.js +++ b/test/identities/identity-provider.spec.js @@ -2,7 +2,7 @@ import assert from 'assert' import path from 'path' import rmrf from 'rimraf' import { KeyStore, Identities } from '../../src/index.js' -import { Identity } from '../../src/identities/index.js' +import { Identity, addIdentityProvider } from '../../src/identities/index.js' import fs from 'fs-extra' const fixturesPath = path.resolve('./test/identities/fixtures/keys') const savedKeysPath = path.resolve('./test/identities/fixtures/savedKeys') @@ -171,7 +171,7 @@ describe('Identity Provider', function () { assert.strictEqual(identity.signatures.id, expectedIdSignature) }) - it('has a pubKeyIdSignature for the publicKey', async () => { + it('has a publicKeyAndIdSignature for the publicKey', async () => { assert.strictEqual(identity.signatures.publicKey, expectedPkIdSignature) }) @@ -179,8 +179,8 @@ describe('Identity Provider', function () { const internalSigningKey = await savedKeysKeyStore.getKey(identity.id) const externalSigningKey = await savedKeysKeyStore.getKey(id) const idSignature = await KeyStore.sign(internalSigningKey, identity.id) - const pubKeyIdSignature = await KeyStore.sign(externalSigningKey, identity.publicKey + idSignature) - const expectedSignature = { id: idSignature, publicKey: pubKeyIdSignature } + const publicKeyAndIdSignature = await KeyStore.sign(externalSigningKey, identity.publicKey + idSignature) + const expectedSignature = { id: idSignature, publicKey: publicKeyAndIdSignature } assert.deepStrictEqual(identity.signatures, expectedSignature) }) }) @@ -234,7 +234,7 @@ describe('Identity Provider', function () { static get type () { return 'fake' } } - identities.addIdentityProvider(IP) + addIdentityProvider(IP) identity = await identities.createIdentity({ type: IP.type }) const verified = await identities.verifyIdentity(identity) assert.strictEqual(verified, false) @@ -309,7 +309,14 @@ describe('Identity Provider', function () { it('throws an error if private key is not found from keystore', async () => { // Remove the key from the keystore (we're using a mock storage in these tests) - const modifiedIdentity = new Identity('this id does not exist', identity.publicKey, '', identity.signatures, identity.type) + const { publicKey, signatures, type } = identity + const modifiedIdentity = await Identity({ + id: 'this id does not exist', + publicKey, + idSignature: '', + publicKeyAndIdSignature: signatures, + type + }) let signature let err try { diff --git a/test/identities/identity.spec.js b/test/identities/identity.spec.js index c92ac2b..e8224a2 100644 --- a/test/identities/identity.spec.js +++ b/test/identities/identity.spec.js @@ -12,7 +12,7 @@ describe('Identity', function () { let identity before(async () => { - identity = new Identity(id, publicKey, idSignature, publicKeyAndIdSignature, type, provider) + identity = await Identity({ id, publicKey, idSignature, publicKeyAndIdSignature, type }) }) it('has the correct id', async () => { @@ -35,21 +35,21 @@ describe('Identity', function () { // assert.deepStrictEqual(identity.provider, provider) // }) - it('converts identity to a JSON object', async () => { - const expected = { - id, - publicKey, - signatures: { id: idSignature, publicKey: publicKeyAndIdSignature }, - type - } - assert.deepStrictEqual(identity.toJSON(), expected) - }) + // it('converts identity to a JSON object', async () => { + // const expected = { + // id, + // publicKey, + // signatures: { id: idSignature, publicKey: publicKeyAndIdSignature }, + // type + // } + // assert.deepStrictEqual(identity.toJSON(), expected) + // }) describe('Constructor inputs', () => { it('throws and error if id was not given in constructor', async () => { let err try { - identity = new Identity() + identity = await Identity() } catch (e) { err = e.toString() } @@ -59,7 +59,7 @@ describe('Identity', function () { it('throws and error if publicKey was not given in constructor', async () => { let err try { - identity = new Identity('abc') + identity = await Identity({ id: 'abc'}) } catch (e) { err = e.toString() } @@ -69,7 +69,7 @@ describe('Identity', function () { it('throws and error if identity signature was not given in constructor', async () => { let err try { - identity = new Identity('abc', publicKey) + identity = await Identity({ id: 'abc', publicKey }) } catch (e) { err = e.toString() } @@ -79,7 +79,7 @@ describe('Identity', function () { it('throws and error if identity signature was not given in constructor', async () => { let err try { - identity = new Identity('abc', publicKey, idSignature) + identity = await Identity({ id: 'abc', publicKey, idSignature }) } catch (e) { err = e.toString() } @@ -99,7 +99,7 @@ describe('Identity', function () { it('throws and error if identity type was not given in constructor', async () => { let err try { - identity = new Identity('abc', publicKey, idSignature, publicKeyAndIdSignature, null, provider) + identity = await Identity({ id: 'abc', publicKey, idSignature, publicKeyAndIdSignature }) } catch (e) { err = e.toString() } diff --git a/test/oplog/entry.test.js b/test/oplog/entry.test.js index 38c5785..7ec4867 100644 --- a/test/oplog/entry.test.js +++ b/test/oplog/entry.test.js @@ -79,7 +79,16 @@ Object.keys(testAPIs).forEach((IPFS) => { }) it('retrieves the identity from an entry', async() => { - const expected = testIdentity.toJSON() + const expected = { + id: testIdentity.id, + publicKey: testIdentity.publicKey, + signatures: testIdentity.signatures, + type: testIdentity.type, + hash: testIdentity.hash, + bytes: testIdentity.bytes, + sign: undefined, + verify: undefined, + } const payload = 'hello world' const entry = await create(testIdentity, 'A', payload) const entryIdentity = await identities.getIdentity(entry.identity) From 0e0c160b209bd76d54e53af8672627b4a6c828f4 Mon Sep 17 00:00:00 2001 From: haad Date: Fri, 17 Feb 2023 11:35:03 +0200 Subject: [PATCH 3/6] Clean up after tests --- .gitignore | 6 +----- src/identities/identities.js | 5 ----- test/document-store.spec.js | 3 --- test/event-store.spec.js | 3 --- test/feed.spec.js | 3 --- test/fixtures/orbit-db-identity-keys.js | 3 +++ test/identities/did-identity-provider.spec.js | 9 +++++---- test/identities/ethereum-identity-provider.spec.js | 9 +++++---- test/keyvalue.spec.js | 3 --- test/oplog/replicate.test.js | 2 -- test/storage.spec.js | 1 - 11 files changed, 14 insertions(+), 33 deletions(-) diff --git a/.gitignore b/.gitignore index 7747369..a3b8770 100644 --- a/.gitignore +++ b/.gitignore @@ -1,13 +1,9 @@ -# Make sure to exclude test data directory -orbitdb/ - # Don't distribute the dependencies node_modules/ #Don't track ipfs files test/ipfs/ test/browser/ipfs/ -test/browser/orbitdb/ test/browser/orbitdb.js test/browser/ipfs.js test/browser/ipfslog.min.js @@ -23,4 +19,4 @@ examples/browser/lib dist/ # Don't track Visual Studio Code settings -.vscode \ No newline at end of file +.vscode diff --git a/src/identities/identities.js b/src/identities/identities.js index 8559fbd..7ff146b 100644 --- a/src/identities/identities.js +++ b/src/identities/identities.js @@ -43,12 +43,7 @@ const Identities = async ({ keystore, signingKeyStore, identityKeysPath, signing const publicKeyAndIdSignature = await identityProvider.signIdentity(publicKey + idSignature, options) const identity = await Identity({ id, publicKey, idSignature, publicKeyAndIdSignature, type, sign, verify }) - // const { hash, bytes } = await encodeIdentity(identity) - // console.log(hash, bytes) await storage.put(identity.hash, identity.bytes) - // const hash = await storage.put(identity.toJSON()) - // // TODO: fix this monkey patching - // identity.hash = hash return identity } diff --git a/test/document-store.spec.js b/test/document-store.spec.js index 4adf65c..1246ab5 100644 --- a/test/document-store.spec.js +++ b/test/document-store.spec.js @@ -95,9 +95,6 @@ Object.keys(testAPIs).forEach((IPFS) => { if (testIdentity2) { rmrf(testIdentity2.id) } - rmrf('./orbitdb') - rmrf('./keys_1') - rmrf('./keys_2') }) describe('using database', () => { diff --git a/test/event-store.spec.js b/test/event-store.spec.js index 44cc513..901af2e 100644 --- a/test/event-store.spec.js +++ b/test/event-store.spec.js @@ -94,9 +94,6 @@ Object.keys(testAPIs).forEach((IPFS) => { if (testIdentity2) { rmrf(testIdentity2.id) } - rmrf('./orbitdb') - rmrf('./keys_1') - rmrf('./keys_2') }) describe('using database', () => { diff --git a/test/feed.spec.js b/test/feed.spec.js index ec97c9c..1d0bad5 100644 --- a/test/feed.spec.js +++ b/test/feed.spec.js @@ -93,9 +93,6 @@ Object.keys(testAPIs).forEach((IPFS) => { if (testIdentity2) { rmrf(testIdentity2.id) } - rmrf('./orbitdb') - rmrf('./keys_1') - rmrf('./keys_2') }) describe('using database', () => { diff --git a/test/fixtures/orbit-db-identity-keys.js b/test/fixtures/orbit-db-identity-keys.js index 79217ed..0f448eb 100644 --- a/test/fixtures/orbit-db-identity-keys.js +++ b/test/fixtures/orbit-db-identity-keys.js @@ -58,6 +58,9 @@ const cleanUpTestIdentities = async (identities) => { await identity.keystore.close() await identity.signingKeyStore.close() } + rmrf('./keys_1') + rmrf('./keys_2') + rmrf('./orbitdb') } export { diff --git a/test/identities/did-identity-provider.spec.js b/test/identities/did-identity-provider.spec.js index dbd0223..ca42641 100644 --- a/test/identities/did-identity-provider.spec.js +++ b/test/identities/did-identity-provider.spec.js @@ -6,18 +6,17 @@ import { Identity, addIdentityProvider } from '../../src/identities/index.js' import { Ed25519Provider } from 'key-did-provider-ed25519' import KeyDidResolver from 'key-did-resolver' import DIDIdentityProvider from '../../src/identities/providers/did.js' -const keypath = path.resolve('./test/identities/fixtures/keys') -let keystore const seed = new Uint8Array([157, 94, 116, 198, 19, 248, 93, 239, 173, 82, 245, 222, 199, 7, 183, 177, 123, 238, 83, 240, 143, 188, 87, 191, 33, 95, 58, 136, 46, 218, 219, 245]) const didStr = 'did:key:z6MkpnTJwrrVuphNh1uKb5DB7eRxvqniVaSDUHU6jtGVmn3r' - const type = DIDIdentityProvider.type + describe('DID Identity Provider', function () { + let keystore let identities before(async () => { - keystore = new KeyStore(keypath) + keystore = new KeyStore() await keystore.open() DIDIdentityProvider.setDIDResolver(KeyDidResolver.getResolver()) addIdentityProvider(DIDIdentityProvider) @@ -28,6 +27,8 @@ describe('DID Identity Provider', function () { if (keystore) { await keystore.close() } + rmrf.sync('./keystore') + rmrf.sync('./orbitdb') }) describe('create an DID identity', () => { diff --git a/test/identities/ethereum-identity-provider.spec.js b/test/identities/ethereum-identity-provider.spec.js index 5530f75..ac65a64 100644 --- a/test/identities/ethereum-identity-provider.spec.js +++ b/test/identities/ethereum-identity-provider.spec.js @@ -5,15 +5,14 @@ import { KeyStore, Identities } from '../../src/index.js' import { Identity, addIdentityProvider } from '../../src/identities/index.js' import EthIdentityProvider from '../../src/identities/providers/ethereum.js' -const keypath = path.resolve('./test/identities/fixtures/keys') -let keystore - const type = EthIdentityProvider.type + describe('Ethereum Identity Provider', function () { + let keystore let identities before(async () => { - keystore = new KeyStore(keypath) + keystore = new KeyStore() await keystore.open() addIdentityProvider(EthIdentityProvider) identities = await Identities({ keystore }) @@ -23,6 +22,8 @@ describe('Ethereum Identity Provider', function () { if (keystore) { await keystore.close() } + rmrf.sync('./keystore') + rmrf.sync('./orbitdb') }) describe('create an ethereum identity', () => { diff --git a/test/keyvalue.spec.js b/test/keyvalue.spec.js index b8f4212..7b33812 100644 --- a/test/keyvalue.spec.js +++ b/test/keyvalue.spec.js @@ -82,9 +82,6 @@ Object.keys(testAPIs).forEach((IPFS) => { if (testIdentity2) { rmrf(testIdentity2.id) } - rmrf('./orbitdb') - rmrf('./keys_1') - rmrf('./keys_2') }) afterEach(async () => { diff --git a/test/oplog/replicate.test.js b/test/oplog/replicate.test.js index 3409fb2..2e0df06 100644 --- a/test/oplog/replicate.test.js +++ b/test/oplog/replicate.test.js @@ -4,7 +4,6 @@ import { copy } from 'fs-extra' import { Log, Entry } from '../../src/index.js' import { MemoryStorage, IPFSBlockStorage } from '../../src/storage/index.js' import { Identities } from '../../src/identities/index.js' -import KeyStore from '../../src/key-store.js' // Test utils import { config, testAPIs, startIpfs, stopIpfs, getIpfsPeerId, waitForPeers, connectPeers } from 'orbit-db-test-utils' @@ -23,7 +22,6 @@ Object.keys(testAPIs).forEach((IPFS) => { let ipfs1, ipfs2 let id1, id2 - let keystore, signingKeyStore let identities1, identities2 let testIdentity1, testIdentity2 let storage1, storage2 diff --git a/test/storage.spec.js b/test/storage.spec.js index 326701c..54e465a 100644 --- a/test/storage.spec.js +++ b/test/storage.spec.js @@ -56,7 +56,6 @@ Object.keys(testAPIs).forEach((_) => { rmrf(identityKeysPath) rmrf(signingKeysPath) rmrf(testIdentity1.id) - rmrf('./orbitdb') rmrf('./ipfs1') }) From 0caa34afcbafb696b24ca2a358570c34beff3e0b Mon Sep 17 00:00:00 2001 From: haad Date: Mon, 20 Feb 2023 10:51:12 +0200 Subject: [PATCH 4/6] Change Identity's signatures structure --- src/identities/identities.js | 6 +- src/identities/identity.js | 107 +++---- src/identities/index.js | 6 +- ....spec.js => did-identity-provider.test.js} | 9 +- ....js => ethereum-identity-provider.test.js} | 9 +- ...ty-provider.spec.js => identities.test.js} | 39 ++- test/identities/identity.spec.js | 109 ------- test/identities/identity.test.js | 269 ++++++++++++++++++ 8 files changed, 374 insertions(+), 180 deletions(-) rename test/identities/{did-identity-provider.spec.js => did-identity-provider.test.js} (96%) rename test/identities/{ethereum-identity-provider.spec.js => ethereum-identity-provider.test.js} (96%) rename test/identities/{identity-provider.spec.js => identities.test.js} (91%) delete mode 100644 test/identities/identity.spec.js create mode 100644 test/identities/identity.test.js diff --git a/src/identities/identities.js b/src/identities/identities.js index 7ff146b..0bc0f7b 100644 --- a/src/identities/identities.js +++ b/src/identities/identities.js @@ -41,7 +41,11 @@ const Identities = async ({ keystore, signingKeyStore, identityKeysPath, signing const publicKey = keystore.getPublic(privateKey) const idSignature = await KeyStore.sign(privateKey, id) const publicKeyAndIdSignature = await identityProvider.signIdentity(publicKey + idSignature, options) - const identity = await Identity({ id, publicKey, idSignature, publicKeyAndIdSignature, type, sign, verify }) + const signatures = { + id: idSignature, + publicKey: publicKeyAndIdSignature + } + const identity = await Identity({ id, publicKey, signatures, type, sign, verify }) await storage.put(identity.hash, identity.bytes) diff --git a/src/identities/identity.js b/src/identities/identity.js index c11e22f..098ed72 100644 --- a/src/identities/identity.js +++ b/src/identities/identity.js @@ -8,53 +8,7 @@ const codec = dagCbor const hasher = sha256 const hashStringEncoding = base58btc -const isEqual = (a, b) => { - return a.id === b.id && - a.publicKey === b.publicKey && - a.signatures.id === b.signatures.id && - a.signatures.publicKey === b.signatures.publicKey -} - -const isIdentity = (identity) => { - return isDefined(identity.id) && - isDefined(identity.publicKey) && - isDefined(identity.signatures) && - isDefined(identity.signatures.id) && - isDefined(identity.signatures.publicKey) && - isDefined(identity.type) -} - -/** - * Encode an Identity to a serializable form - * @param {Identity} identity Identity to encode - * @returns {Object} Object with fields hash and bytes - */ -const encodeIdentity = async (identity) => { - const { id, publicKey, signatures, type } = identity - const value = { id, publicKey, signatures, type } - const { cid, bytes } = await Block.encode({ value, codec, hasher }) - const hash = cid.toString(hashStringEncoding) - return { hash, bytes } -} - -/** - * Decode an Identity from bytes - * @param {Uint8Array} bytes Bytes from which to decode an Identity from - * @returns {Identity} - */ -const decodeIdentity = async (bytes) => { - const { value } = await Block.decode({ bytes, codec, hasher }) - const { id, publicKey, signatures, type } = value - return Identity({ - id, - publicKey, - idSignature: signatures.id, - publicKeyAndIdSignature: signatures.publicKey, - type - }) -} - -const Identity = async ({ id, publicKey, idSignature, publicKeyAndIdSignature, type, sign, verify } = {}) => { +const Identity = async ({ id, publicKey, signatures, type, sign, verify } = {}) => { if (!isDefined(id)) { throw new Error('Identity id is required') } @@ -63,11 +17,15 @@ const Identity = async ({ id, publicKey, idSignature, publicKeyAndIdSignature, t throw new Error('Invalid public key') } - if (!isDefined(idSignature)) { - throw new Error('Signature of the id (idSignature) is required') + if (!isDefined(signatures)) { + throw new Error('Signatures is required') } - if (!isDefined(publicKeyAndIdSignature)) { + 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') } @@ -75,7 +33,7 @@ const Identity = async ({ id, publicKey, idSignature, publicKeyAndIdSignature, t throw new Error('Identity type is required') } - const signatures = Object.assign({}, { id: idSignature }, { publicKey: publicKeyAndIdSignature }) + signatures = Object.assign({}, signatures) const identity = { id, @@ -86,11 +44,54 @@ const Identity = async ({ id, publicKey, idSignature, publicKeyAndIdSignature, t verify } - const { hash, bytes } = await encodeIdentity(identity) + const { hash, bytes } = await _encodeIdentity(identity) identity.hash = hash identity.bytes = bytes return identity } -export { Identity as default, isEqual, isIdentity, encodeIdentity, decodeIdentity } +/** + * Encode an Identity to a serializable form + * @param {Identity} identity Identity to encode + * @returns {Object} Object with fields hash and bytes + */ +const _encodeIdentity = async (identity) => { + const { id, publicKey, signatures, type } = identity + const value = { id, publicKey, signatures, type } + const { cid, bytes } = await Block.encode({ value, codec, hasher }) + const hash = cid.toString(hashStringEncoding) + return { hash, bytes: Uint8Array.from(bytes) } +} + +/** + * Decode an Identity from bytes + * @param {Uint8Array} bytes Bytes from which to decode an Identity from + * @returns {Identity} + */ +const decodeIdentity = async (bytes) => { + const { value } = await Block.decode({ bytes, codec, hasher }) + return Identity({ ...value }) +} + +const isIdentity = (identity) => { + return isDefined(identity.id) && + isDefined(identity.hash) && + isDefined(identity.bytes) && + isDefined(identity.publicKey) && + isDefined(identity.signatures) && + isDefined(identity.signatures.id) && + isDefined(identity.signatures.publicKey) && + isDefined(identity.type) +} + +const isEqual = (a, b) => { + return a.id === b.id && + a.hash === b.hash && + a.type === b.type && + a.publicKey === b.publicKey && + a.signatures.id === b.signatures.id && + a.signatures.publicKey === b.signatures.publicKey +} + +export { Identity as default, isEqual, isIdentity, decodeIdentity } diff --git a/src/identities/index.js b/src/identities/index.js index c24f0bb..fb40316 100644 --- a/src/identities/index.js +++ b/src/identities/index.js @@ -5,4 +5,8 @@ export { isProviderSupported } from './identities.js' -export { default as Identity } from './identity.js' +export { + default as Identity, + isIdentity, + isEqual +} from './identity.js' diff --git a/test/identities/did-identity-provider.spec.js b/test/identities/did-identity-provider.test.js similarity index 96% rename from test/identities/did-identity-provider.spec.js rename to test/identities/did-identity-provider.test.js index ca42641..c7d842d 100644 --- a/test/identities/did-identity-provider.spec.js +++ b/test/identities/did-identity-provider.test.js @@ -87,8 +87,7 @@ describe('DID Identity Provider', function () { const identity2 = await Identity({ id: 'NotAnId', publicKey, - idSignature: signatures.id, - publicKeyAndIdSignature: signatures.publicKey, + signatures, type }) const verified = await identities.verifyIdentity(identity2) @@ -118,8 +117,10 @@ describe('DID Identity Provider', function () { const modifiedIdentity = await Identity({ id: 'this id does not exist', publicKey, - idSignature: '', - publicKeyAndIdSignature: signatures.publicKey, + signatures: { + id: '', + publicKey: signatures.publicKey + }, type }) let signature diff --git a/test/identities/ethereum-identity-provider.spec.js b/test/identities/ethereum-identity-provider.test.js similarity index 96% rename from test/identities/ethereum-identity-provider.spec.js rename to test/identities/ethereum-identity-provider.test.js index ac65a64..7af290a 100644 --- a/test/identities/ethereum-identity-provider.spec.js +++ b/test/identities/ethereum-identity-provider.test.js @@ -84,8 +84,7 @@ describe('Ethereum Identity Provider', function () { const identity2 = await Identity({ id: 'NotAnId', publicKey, - idSignature: signatures.id, - publicKeyAndIdSignature: signatures.publicKey, + signatures, type }) const verified = await identities.verifyIdentity(identity2) @@ -114,8 +113,10 @@ describe('Ethereum Identity Provider', function () { const modifiedIdentity = await Identity({ id: 'this id does not exist', publicKey, - idSignature: '', - publicKeyAndIdSignature: signatures.publicKey, + signatures: { + id: '', + publicKey: signatures.publicKey, + }, type }) let signature diff --git a/test/identities/identity-provider.spec.js b/test/identities/identities.test.js similarity index 91% rename from test/identities/identity-provider.spec.js rename to test/identities/identities.test.js index 4aca241..e967ceb 100644 --- a/test/identities/identity-provider.spec.js +++ b/test/identities/identities.test.js @@ -10,7 +10,7 @@ const signingKeysPath = path.resolve('./test/identities/signingKeys') const identityKeysPath = path.resolve('./test/identities/identityKeys') const type = 'orbitdb' -describe('Identity Provider', function () { +describe('Identities', function () { before(async () => { rmrf.sync(signingKeysPath) rmrf.sync(identityKeysPath) @@ -53,6 +53,35 @@ describe('Identity Provider', function () { }) }) + describe('Get Identity', () => { + const id = 'A' + + let identities + let identity + + afterEach(async () => { + if (identities) { + await identities.keystore.close() + } + if (identities) { + await identities.signingKeyStore.close() + } + }) + + it('gets the identity from storage', async () => { + identities = await Identities({ identityKeysPath, signingKeysPath }) + identity = await identities.createIdentity({ id }) + const result = await identities.getIdentity(identity.hash) + assert.strictEqual(result.id, identity.id) + assert.strictEqual(result.hash, identity.hash) + assert.strictEqual(result.publicKey, identity.publicKey) + assert.strictEqual(result.type, identity.type) + assert.deepStrictEqual(result.signatures, identity.signatures) + assert.strictEqual(result.sign, undefined) + assert.strictEqual(result.verify, undefined) + }) + }) + describe('Passing in custom keystore', async () => { const id = 'B' @@ -310,13 +339,7 @@ describe('Identity Provider', function () { it('throws an error if private key is not found from keystore', async () => { // Remove the key from the keystore (we're using a mock storage in these tests) const { publicKey, signatures, type } = identity - const modifiedIdentity = await Identity({ - id: 'this id does not exist', - publicKey, - idSignature: '', - publicKeyAndIdSignature: signatures, - type - }) + const modifiedIdentity = await Identity({ id: 'this id does not exist', publicKey, signatures, type }) let signature let err try { diff --git a/test/identities/identity.spec.js b/test/identities/identity.spec.js deleted file mode 100644 index e8224a2..0000000 --- a/test/identities/identity.spec.js +++ /dev/null @@ -1,109 +0,0 @@ -import assert from 'assert' -import { Identity } from '../../src/identities/index.js' - -describe('Identity', function () { - const id = '0x01234567890abcdefghijklmnopqrstuvwxyz' - const publicKey = '' - const idSignature = 'signature for ' - const publicKeyAndIdSignature = 'signature for ' - const type = 'orbitdb' - const provider = 'IdentityProviderInstance' - - let identity - - before(async () => { - identity = await Identity({ id, publicKey, idSignature, publicKeyAndIdSignature, type }) - }) - - it('has the correct id', async () => { - assert.strictEqual(identity.id, id) - }) - - it('has the correct publicKey', async () => { - assert.strictEqual(identity.publicKey, publicKey) - }) - - it('has the correct idSignature', async () => { - assert.strictEqual(identity.signatures.id, idSignature) - }) - - it('has the correct publicKeyAndIdSignature', async () => { - assert.strictEqual(identity.signatures.publicKey, publicKeyAndIdSignature) - }) - - // it('has the correct provider', async () => { - // assert.deepStrictEqual(identity.provider, provider) - // }) - - // it('converts identity to a JSON object', async () => { - // const expected = { - // id, - // publicKey, - // signatures: { id: idSignature, publicKey: publicKeyAndIdSignature }, - // type - // } - // assert.deepStrictEqual(identity.toJSON(), expected) - // }) - - describe('Constructor inputs', () => { - it('throws and error if id was not given in constructor', async () => { - let err - try { - identity = await Identity() - } catch (e) { - err = e.toString() - } - assert.strictEqual(err, 'Error: Identity id is required') - }) - - it('throws and error if publicKey was not given in constructor', async () => { - let err - try { - identity = await Identity({ id: 'abc'}) - } catch (e) { - err = e.toString() - } - assert.strictEqual(err, 'Error: Invalid public key') - }) - - it('throws and error if identity signature was not given in constructor', async () => { - let err - try { - identity = await Identity({ id: 'abc', publicKey }) - } catch (e) { - err = e.toString() - } - assert.strictEqual(err, 'Error: Signature of the id (idSignature) is required') - }) - - it('throws and error if identity signature was not given in constructor', async () => { - let err - try { - identity = await Identity({ id: 'abc', publicKey, idSignature }) - } catch (e) { - err = e.toString() - } - assert.strictEqual(err, 'Error: Signature of (publicKey + idSignature) is required') - }) - - // it('throws and error if identity provider was not given in constructor', async () => { - // let err - // try { - // identity = new Identity('abc', publicKey, idSignature, publicKeyAndIdSignature, type) - // } catch (e) { - // err = e.toString() - // } - // assert.strictEqual(err, 'Error: Identity provider is required') - // }) - - it('throws and error if identity type was not given in constructor', async () => { - let err - try { - identity = await Identity({ id: 'abc', publicKey, idSignature, publicKeyAndIdSignature }) - } catch (e) { - err = e.toString() - } - assert.strictEqual(err, 'Error: Identity type is required') - }) - }) -}) diff --git a/test/identities/identity.test.js b/test/identities/identity.test.js new file mode 100644 index 0000000..6e93994 --- /dev/null +++ b/test/identities/identity.test.js @@ -0,0 +1,269 @@ +import assert from 'assert' +import { Identity, isIdentity, isEqual } from '../../src/identities/index.js' +import { decodeIdentity } from '../../src/identities/identity.js' + +describe('Identity', function () { + const id = '0x01234567890abcdefghijklmnopqrstuvwxyz' + const publicKey = '' + const signatures = { + id: 'signature for ', + publicKey: 'signature for ' + } + const type = 'orbitdb' + // const provider = 'IdentityProviderInstance' + + const expectedHash = 'zdpuArx43BnXdDff5rjrGLYrxUomxNroc2uaocTgcWK76UfQT' + const expectedBytes = Uint8Array.from([ + 164,98,105,100,120,39,48,120,48,49,50,51,52,53,54,55,56,57,48,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,100,116,121,112,101,103,111,114,98,105,116,100,98,105,112,117,98,108,105,99,75,101,121,104,60,112,117,98,107,101,121,62,106,115,105,103,110,97,116,117,114,101,115,162,98,105,100,114,115,105,103,110,97,116,117,114,101,32,102,111,114,32,60,105,100,62,105,112,117,98,108,105,99,75,101,121,120,39,115,105,103,110,97,116,117,114,101,32,102,111,114,32,60,112,117,98,108,105,99,75,101,121,32,43,32,105,100,83,105,103,110,97,116,117,114,101,62 + ]) + + let identity + + before(async () => { + identity = await Identity({ id, publicKey, signatures, type }) + }) + + it('has the correct id', async () => { + assert.strictEqual(identity.id, id) + }) + + it('has the correct publicKey', async () => { + assert.strictEqual(identity.publicKey, publicKey) + }) + + it('has the correct idSignature', async () => { + assert.strictEqual(identity.signatures.id, signatures.id) + }) + + it('has the correct publicKeyAndIdSignature', async () => { + assert.strictEqual(identity.signatures.publicKey, signatures.publicKey) + }) + + // it('has the correct provider', async () => { + // assert.deepStrictEqual(identity.provider, provider) + // }) + + describe('Constructor inputs', () => { + it('throws and error if id was not given in constructor', async () => { + let err + try { + identity = await Identity() + } catch (e) { + err = e.toString() + } + assert.strictEqual(err, 'Error: Identity id is required') + }) + + it('throws and error if publicKey was not given in constructor', async () => { + let err + try { + identity = await Identity({ id: 'abc'}) + } catch (e) { + err = e.toString() + } + assert.strictEqual(err, 'Error: Invalid public key') + }) + + it('throws and error if identity signature was not given in constructor', async () => { + let err + try { + identity = await Identity({ id: 'abc', publicKey }) + } catch (e) { + err = e.toString() + } + assert.strictEqual(err, 'Error: Signatures is required') + }) + + it('throws and error if signature for id was not given in constructor', async () => { + let err + try { + identity = await Identity({ id: 'abc', publicKey, signatures: {} }) + } catch (e) { + err = e.toString() + } + assert.strictEqual(err, 'Error: Signature of the id is required') + }) + + it('throws and error if signature for publicKey was not given in constructor', async () => { + let err + try { + identity = await Identity({ id: 'abc', publicKey, signatures: { id: signatures.id } }) + } catch (e) { + err = e.toString() + } + assert.strictEqual(err, 'Error: Signature of (publicKey + idSignature) is required') + }) + + it('throws and error if signature for publicKey was not given in constructor', async () => { + let err + try { + identity = await Identity({ id: 'abc', publicKey, signatures: { publicKey: signatures.publicKey } }) + } catch (e) { + err = e.toString() + } + assert.strictEqual(err, 'Error: Signature of the id is required') + }) + + // it('throws and error if identity provider was not given in constructor', async () => { + // let err + // try { + // identity = new Identity('abc', publicKey, idSignature, publicKeyAndIdSignature, type) + // } catch (e) { + // err = e.toString() + // } + // assert.strictEqual(err, 'Error: Identity provider is required') + // }) + + it('throws and error if identity type was not given in constructor', async () => { + let err + try { + identity = await Identity({ id: 'abc', publicKey, signatures }) + } catch (e) { + err = e.toString() + } + assert.strictEqual(err, 'Error: Identity type is required') + }) + }) + + describe('isIdentity', () => { + describe('valid Identity', () => { + it('is a valid identity', async () => { + const identity = await Identity({ id, publicKey, signatures, type }) + const result = isIdentity(identity) + assert.strictEqual(result, true) + }) + }) + + describe('invalid Identity', () => { + beforeEach(async () => { + identity = await Identity({ id, publicKey, signatures, type }) + }) + + it('is not a valid identity if id is missing', async () => { + delete identity.id + const result = isIdentity(identity) + assert.strictEqual(result, false) + }) + + it('is not a valid identity if hash is missing', async () => { + delete identity.hash + const result = isIdentity(identity) + assert.strictEqual(result, false) + }) + + it('is not a valid identity if bytes are missing', async () => { + delete identity.bytes + const result = isIdentity(identity) + assert.strictEqual(result, false) + }) + + it('is not a valid identity if publicKey is missing', async () => { + delete identity.publicKey + const result = isIdentity(identity) + assert.strictEqual(result, false) + }) + + it('is not a valid identity if signatures is missing', async () => { + delete identity.signatures + const result = isIdentity(identity) + assert.strictEqual(result, false) + }) + + it('is not a valid identity if signature for id is missing', async () => { + delete identity.signatures.id + const result = isIdentity(identity) + assert.strictEqual(result, false) + }) + + it('is not a valid identity if signature for publicKey is missing', async () => { + delete identity.signatures.publicKey + const result = isIdentity(identity) + assert.strictEqual(result, false) + }) + + it('is not a valid identity if type is missing', async () => { + delete identity.type + const result = isIdentity(identity) + assert.strictEqual(result, false) + }) + }) + }) + + describe('isEqual', () => { + describe('equal identities', () => { + it('identities are equal', async () => { + const identity1 = await Identity({ id, publicKey, signatures, type }) + const identity2 = await Identity({ id, publicKey, signatures, type }) + const result = isEqual(identity1, identity2) + assert.strictEqual(result, true) + }) + }) + + describe('not equal identities', () => { + let identity1, identity2 + + before(async () => { + identity1 = await Identity({ id, publicKey, signatures, type }) + identity2 = await Identity({ id, publicKey, signatures, type }) + }) + + it('identities are not equal if id is different', async () => { + identity2 = await Identity({ id: 'X', publicKey, signatures, type }) + const result = isEqual(identity1, identity2) + assert.strictEqual(result, false) + }) + + it('identities are not equal if hash is different', async () => { + identity2 = await Identity({ id, publicKey, signatures, type }) + identity2.hash = 'notthesame' + const result = isEqual(identity1, identity2) + assert.strictEqual(result, false) + }) + + it('identities are not equal if type is different', async () => { + identity2 = await Identity({ id, publicKey, signatures, type }) + identity2.type = 'some other identity provider than orbitdb' + const result = isEqual(identity1, identity2) + assert.strictEqual(result, false) + }) + + it('identities are not equal if publicKey is different', async () => { + identity2 = await Identity({ id, publicKey: 'XYZ', signatures, type }) + const result = isEqual(identity1, identity2) + assert.strictEqual(result, false) + }) + + it('identities are not equal if id signature is different', async () => { + identity2 = await Identity({ id, publicKey, signatures: { id: 'different id signature', publicKey: signatures.publicKey }, type }) + const result = isEqual(identity1, identity2) + assert.strictEqual(result, false) + }) + + it('identities are not equal if publicKey signature is different', async () => { + identity2 = await Identity({ id, publicKey, signatures: { id: signatures.id, publicKey: 'different publicKey signature' }, type }) + const result = isEqual(identity1, identity2) + assert.strictEqual(result, false) + }) + }) + }) + + describe('Decode Identity', () => { + before(async () => { + identity = await Identity({ id, publicKey, signatures, type }) + }) + + it('decodes an identity from bytes', async () => { + const result = await decodeIdentity(expectedBytes) + + assert.strictEqual(isIdentity(result), true) + assert.strictEqual(result.id, id) + assert.strictEqual(result.publicKey, publicKey) + assert.strictEqual(result.type, type) + assert.strictEqual(result.hash, expectedHash) + assert.strictEqual(result.sign, undefined) + assert.strictEqual(result.verify, undefined) + assert.deepStrictEqual(result.bytes, expectedBytes) + assert.deepStrictEqual(result.signatures, signatures) + }) + }) +}) From f84915fca8c332387208cb45e4238bde37e8ae09 Mon Sep 17 00:00:00 2001 From: haad Date: Mon, 20 Feb 2023 11:21:34 +0200 Subject: [PATCH 5/6] Merge identity keys and signing keys keystores --- Makefile | 1 - src/identities/identities.js | 8 ++-- test/document-store.spec.js | 7 +-- test/event-store.spec.js | 7 +-- test/feed.spec.js | 7 +-- test/fixtures/orbit-db-identity-keys.js | 11 ++--- test/identities/identities.test.js | 64 +++---------------------- test/keyvalue.spec.js | 7 +-- test/oplog/append.test.js | 15 ++---- test/oplog/crdt.test.js | 16 +++---- test/oplog/entry.test.js | 16 +++---- test/oplog/heads.test.js | 16 +++---- test/oplog/iterator.test.js | 17 ++----- test/oplog/join-concurrent.test.js | 15 +++--- test/oplog/join.test.js | 19 +++----- test/oplog/load.test.js | 22 ++++----- test/oplog/log.test.js | 14 ++---- test/oplog/references.test.js | 14 ++---- test/oplog/replicate.test.js | 7 --- test/oplog/signed-log.test.js | 2 +- test/storage.spec.js | 15 ++---- 21 files changed, 86 insertions(+), 214 deletions(-) diff --git a/Makefile b/Makefile index 5da0ad1..45c4aaf 100644 --- a/Makefile +++ b/Makefile @@ -18,7 +18,6 @@ build: test @echo "Output: 'dist/', 'examples/browser/'" clean: - rm -rf orbitdb/ rm -rf node_modules/ rm -f test/browser/identities.js rm -f test/browser/ipfs.js diff --git a/src/identities/identities.js b/src/identities/identities.js index 0bc0f7b..768b6f1 100644 --- a/src/identities/identities.js +++ b/src/identities/identities.js @@ -15,9 +15,8 @@ const supportedTypes = { // [EthIdentityProvider.type]: EthIdentityProvider } -const Identities = async ({ keystore, signingKeyStore, identityKeysPath, signingKeysPath, storage, ipfs } = {}) => { +const Identities = async ({ keystore, identityKeysPath, storage, ipfs } = {}) => { keystore = keystore || new KeyStore(identityKeysPath || DefaultIdentityKeysPath) - signingKeyStore = signingKeyStore || (signingKeysPath ? new KeyStore(signingKeysPath) : keystore) storage = storage || (ipfs ? await IPFSBlockStorage({ ipfs, pin: true }) : await MemoryStorage()) const verifiedIdentitiesCache = await LRUStorage({ size: 1000 }) @@ -30,7 +29,7 @@ const Identities = async ({ keystore, signingKeyStore, identityKeysPath, signing } const createIdentity = async (options = {}) => { - options.keystore = signingKeyStore || keystore + options.keystore = keystore const type = options.type || DefaultProviderType const Provider = getProviderFor(type) @@ -99,8 +98,7 @@ const Identities = async ({ keystore, signingKeyStore, identityKeysPath, signing getIdentity, sign, verify, - keystore, - signingKeyStore + keystore } } diff --git a/test/document-store.spec.js b/test/document-store.spec.js index 1246ab5..052c0ef 100644 --- a/test/document-store.spec.js +++ b/test/document-store.spec.js @@ -9,7 +9,7 @@ import { IPFSBlockStorage, LevelStorage } from '../src/storage/index.js' // import { config, testAPIs, getIpfsPeerId, waitForPeers, startIpfs, stopIpfs } from 'orbit-db-test-utils' import { config, testAPIs, startIpfs, stopIpfs } from 'orbit-db-test-utils' import connectPeers from './utils/connect-nodes.js' -import { identityKeys, signingKeys, createTestIdentities, cleanUpTestIdentities } from './fixtures/orbit-db-identity-keys.js' +import { createTestIdentities, cleanUpTestIdentities } from './fixtures/orbit-db-identity-keys.js' const { sync: rmrf } = rimraf @@ -21,7 +21,7 @@ Object.keys(testAPIs).forEach((IPFS) => { let ipfsd1, ipfsd2 let ipfs1, ipfs2 - let keystore, signingKeyStore + let keystore // let peerId1, peerId2 let identities1, identities2 let testIdentity1, testIdentity2 @@ -86,9 +86,6 @@ Object.keys(testAPIs).forEach((IPFS) => { if (keystore) { await keystore.close() } - if (signingKeyStore) { - await signingKeyStore.close() - } if (testIdentity1) { rmrf(testIdentity1.id) } diff --git a/test/event-store.spec.js b/test/event-store.spec.js index 901af2e..633c421 100644 --- a/test/event-store.spec.js +++ b/test/event-store.spec.js @@ -10,7 +10,7 @@ import { IPFSBlockStorage, LevelStorage } from '../src/storage/index.js' import { config, testAPIs, startIpfs, stopIpfs, getIpfsPeerId, waitForPeers } from 'orbit-db-test-utils' import connectPeers from './utils/connect-nodes.js' import waitFor from './utils/wait-for.js' -import { identityKeys, signingKeys, createTestIdentities, cleanUpTestIdentities } from './fixtures/orbit-db-identity-keys.js' +import { createTestIdentities, cleanUpTestIdentities } from './fixtures/orbit-db-identity-keys.js' const { sync: rmrf } = rimraf const { createIdentity } = Identities @@ -23,7 +23,7 @@ Object.keys(testAPIs).forEach((IPFS) => { let ipfsd1, ipfsd2 let ipfs1, ipfs2 - let keystore, signingKeyStore + let keystore let peerId1, peerId2 let identities1, identities2 let testIdentity1, testIdentity2 @@ -85,9 +85,6 @@ Object.keys(testAPIs).forEach((IPFS) => { if (keystore) { await keystore.close() } - if (signingKeyStore) { - await signingKeyStore.close() - } if (testIdentity1) { rmrf(testIdentity1.id) } diff --git a/test/feed.spec.js b/test/feed.spec.js index 1d0bad5..132841e 100644 --- a/test/feed.spec.js +++ b/test/feed.spec.js @@ -10,7 +10,7 @@ import { IPFSBlockStorage, LevelStorage } from '../src/storage/index.js' import { config, testAPIs, getIpfsPeerId, waitForPeers, startIpfs, stopIpfs } from 'orbit-db-test-utils' import connectPeers from './utils/connect-nodes.js' import waitFor from './utils/wait-for.js' -import { identityKeys, signingKeys, createTestIdentities, cleanUpTestIdentities } from './fixtures/orbit-db-identity-keys.js' +import { createTestIdentities, cleanUpTestIdentities } from './fixtures/orbit-db-identity-keys.js' const { sync: rmrf } = rimraf const { createIdentity } = Identities @@ -22,7 +22,7 @@ Object.keys(testAPIs).forEach((IPFS) => { let ipfsd1, ipfsd2 let ipfs1, ipfs2 - let keystore, signingKeyStore + let keystore let peerId1, peerId2 let identities1, identities2 let testIdentity1, testIdentity2 @@ -84,9 +84,6 @@ Object.keys(testAPIs).forEach((IPFS) => { if (keystore) { await keystore.close() } - if (signingKeyStore) { - await signingKeyStore.close() - } if (testIdentity1) { rmrf(testIdentity1.id) } diff --git a/test/fixtures/orbit-db-identity-keys.js b/test/fixtures/orbit-db-identity-keys.js index 0f448eb..f0a5a36 100644 --- a/test/fixtures/orbit-db-identity-keys.js +++ b/test/fixtures/orbit-db-identity-keys.js @@ -30,7 +30,6 @@ const signingKeys = { const createTestIdentities = async (ipfs1, ipfs2) => { rmrf('./keys_1') - rmrf('./keys_2') const keystore = new KeyStore('./keys_1') await keystore.open() @@ -38,15 +37,13 @@ const createTestIdentities = async (ipfs1, ipfs2) => { await keystore.addKey(key, value) } - const signingKeyStore = new KeyStore('./keys_2') - await signingKeyStore.open() for (const [key, value] of Object.entries(signingKeys)) { - await signingKeyStore.addKey(key, value) + await keystore.addKey(key, value) } // Create an identity for each peers - const identities1 = await Identities({ keystore, signingKeyStore, ipfs: ipfs1 }) - const identities2 = await Identities({ keystore, signingKeyStore, ipfs: ipfs2 }) + const identities1 = await Identities({ keystore, ipfs: ipfs1 }) + const identities2 = await Identities({ keystore, ipfs: ipfs2 }) const testIdentity1 = await identities1.createIdentity({ id: 'userA' }) const testIdentity2 = await identities2.createIdentity({ id: 'userB' }) @@ -56,10 +53,8 @@ const createTestIdentities = async (ipfs1, ipfs2) => { const cleanUpTestIdentities = async (identities) => { for (let identity of identities) { await identity.keystore.close() - await identity.signingKeyStore.close() } rmrf('./keys_1') - rmrf('./keys_2') rmrf('./orbitdb') } diff --git a/test/identities/identities.test.js b/test/identities/identities.test.js index e967ceb..289df24 100644 --- a/test/identities/identities.test.js +++ b/test/identities/identities.test.js @@ -6,18 +6,15 @@ import { Identity, addIdentityProvider } from '../../src/identities/index.js' import fs from 'fs-extra' const fixturesPath = path.resolve('./test/identities/fixtures/keys') const savedKeysPath = path.resolve('./test/identities/fixtures/savedKeys') -const signingKeysPath = path.resolve('./test/identities/signingKeys') const identityKeysPath = path.resolve('./test/identities/identityKeys') const type = 'orbitdb' describe('Identities', function () { before(async () => { - rmrf.sync(signingKeysPath) rmrf.sync(identityKeysPath) }) after(async () => { - rmrf.sync(signingKeysPath) rmrf.sync(identityKeysPath) }) @@ -31,26 +28,15 @@ describe('Identities', function () { if (identities) { await identities.keystore.close() } - if (identities) { - await identities.signingKeyStore.close() - } }) - it('identityKeysPath only - has the correct id', async () => { + it('has the correct id', async () => { identities = await Identities({ identityKeysPath }) identity = await identities.createIdentity({ id }) const key = await identities.keystore.getKey(id) const externalId = Buffer.from(key.public.marshal()).toString('hex') assert.strictEqual(identity.id, externalId) }) - - it('identityKeysPath and signingKeysPath - has a different id', async () => { - identities = await Identities({ identityKeysPath, signingKeysPath }) - identity = await identities.createIdentity({ id }) - const key = await identities.keystore.getKey(id) - const externalId = Buffer.from(key.public.marshal()).toString('hex') - assert.notStrictEqual(identity.id, externalId) - }) }) describe('Get Identity', () => { @@ -63,13 +49,10 @@ describe('Identities', function () { if (identities) { await identities.keystore.close() } - if (identities) { - await identities.signingKeyStore.close() - } }) it('gets the identity from storage', async () => { - identities = await Identities({ identityKeysPath, signingKeysPath }) + identities = await Identities({ identityKeysPath }) identity = await identities.createIdentity({ id }) const result = await identities.getIdentity(identity.hash) assert.strictEqual(result.id, identity.id) @@ -88,13 +71,10 @@ describe('Identities', function () { let identity let identities let keystore - let signingKeyStore before(async () => { keystore = new KeyStore(identityKeysPath) await keystore.open() - signingKeyStore = new KeyStore(signingKeysPath) - await signingKeyStore.open() identities = await Identities({ keystore }) }) @@ -102,9 +82,6 @@ describe('Identities', function () { if (keystore) { await keystore.close() } - if (signingKeyStore) { - await signingKeyStore.close() - } }) it('has the correct id', async () => { @@ -177,9 +154,6 @@ describe('Identities', function () { if (identities) { await identities.keystore.close() } - if (identities) { - await identities.signingKeyStore.close() - } rmrf.sync(savedKeysPath) }) @@ -220,33 +194,27 @@ describe('Identities', function () { let identities let identity let keystore - let signingKeyStore before(async () => { keystore = new KeyStore(identityKeysPath) await keystore.open() - signingKeyStore = new KeyStore(signingKeysPath) - await signingKeyStore.open() }) after(async () => { if (keystore) { await keystore.close() } - if (signingKeyStore) { - await signingKeyStore.close() - } }) it('identity pkSignature verifies', async () => { - identities = await Identities({ keystore, signingKeyStore }) + identities = await Identities({ keystore }) identity = await identities.createIdentity({ id, type }) const verified = await KeyStore.verify(identity.signatures.id, identity.publicKey, identity.id) assert.strictEqual(verified, true) }) it('identity signature verifies', async () => { - identities = await Identities({ keystore, signingKeyStore }) + identities = await Identities({ keystore }) identity = await identities.createIdentity({ id, type }) const verified = await KeyStore.verify(identity.signatures.publicKey, identity.id, identity.publicKey + identity.signatures.id) assert.strictEqual(verified, true) @@ -276,23 +244,17 @@ describe('Identities', function () { let identities let identity let keystore - let signingKeyStore before(async () => { keystore = new KeyStore(identityKeysPath) await keystore.open() - signingKeyStore = new KeyStore(signingKeysPath) - await signingKeyStore.open() - identities = await Identities({ keystore, signingKeyStore }) + identities = await Identities({ keystore }) }) after(async () => { if (keystore) { await keystore.close() } - if (signingKeyStore) { - await signingKeyStore.close() - } }) it('identity verifies', async () => { @@ -309,14 +271,11 @@ describe('Identities', function () { let identities let identity let keystore - let signingKeyStore before(async () => { keystore = new KeyStore(identityKeysPath) await keystore.open() - signingKeyStore = new KeyStore(signingKeysPath) - await signingKeyStore.open() - identities = await Identities({ keystore, signingKeyStore }) + identities = await Identities({ keystore }) identity = await identities.createIdentity({ id }) }) @@ -324,9 +283,6 @@ describe('Identities', function () { if (keystore) { await keystore.close() } - if (signingKeyStore) { - await signingKeyStore.close() - } }) it('sign data', async () => { @@ -359,27 +315,21 @@ describe('Identities', function () { let identities let identity let keystore - let signingKeyStore let signature before(async () => { keystore = new KeyStore(identityKeysPath) await keystore.open() - signingKeyStore = new KeyStore(signingKeysPath) - await signingKeyStore.open() }) after(async () => { if (keystore) { await keystore.close() } - if (signingKeyStore) { - await signingKeyStore.close() - } }) beforeEach(async () => { - identities = await Identities({ keystore, signingKeyStore }) + identities = await Identities({ keystore }) identity = await identities.createIdentity({ id, type }) signature = await identities.sign(identity, data, keystore) }) diff --git a/test/keyvalue.spec.js b/test/keyvalue.spec.js index 7b33812..03234dd 100644 --- a/test/keyvalue.spec.js +++ b/test/keyvalue.spec.js @@ -10,7 +10,7 @@ import { IPFSBlockStorage, LevelStorage } from '../src/storage/index.js' import { config, testAPIs, getIpfsPeerId, waitForPeers, startIpfs, stopIpfs } from 'orbit-db-test-utils' import connectPeers from './utils/connect-nodes.js' import waitFor from './utils/wait-for.js' -import { identityKeys, signingKeys, createTestIdentities, cleanUpTestIdentities } from './fixtures/orbit-db-identity-keys.js' +import { createTestIdentities, cleanUpTestIdentities } from './fixtures/orbit-db-identity-keys.js' const { sync: rmrf } = rimraf const { createIdentity } = Identities @@ -23,7 +23,7 @@ Object.keys(testAPIs).forEach((IPFS) => { let ipfsd1, ipfsd2 let ipfs1, ipfs2 - let keystore, signingKeyStore + let keystore let peerId1, peerId2 let identities1, identities2 let testIdentity1, testIdentity2 @@ -73,9 +73,6 @@ Object.keys(testAPIs).forEach((IPFS) => { if (keystore) { await keystore.close() } - if (signingKeyStore) { - await signingKeyStore.close() - } if (testIdentity1) { rmrf(testIdentity1.id) } diff --git a/test/oplog/append.test.js b/test/oplog/append.test.js index bffe79d..e221cf7 100644 --- a/test/oplog/append.test.js +++ b/test/oplog/append.test.js @@ -18,32 +18,27 @@ Object.keys(testAPIs).forEach((IPFS) => { describe('Log - Append (' + IPFS + ')', function () { this.timeout(config.timeout) - const { identityKeyFixtures, signingKeyFixtures, identityKeysPath, signingKeysPath } = config + const { identityKeyFixtures, signingKeyFixtures, identityKeysPath } = config - let keystore, signingKeyStore + let keystore let identities before(async () => { rmrf(identityKeysPath) - rmrf(signingKeysPath) await copy(identityKeyFixtures, identityKeysPath) - await copy(signingKeyFixtures, signingKeysPath) + await copy(signingKeyFixtures, identityKeysPath) keystore = new KeyStore(identityKeysPath) - signingKeyStore = new KeyStore(signingKeysPath) const storage = await MemoryStorage() - identities = await Identities({ keystore, signingKeyStore, storage }) + identities = await Identities({ keystore, storage }) testIdentity = await identities.createIdentity({ id: 'userA' }) }) after(async () => { - rmrf(identityKeysPath) - rmrf(signingKeysPath) - await keystore.close() - await signingKeyStore.close() + rmrf(identityKeysPath) }) describe('append', async () => { diff --git a/test/oplog/crdt.test.js b/test/oplog/crdt.test.js index 74e589d..3337243 100644 --- a/test/oplog/crdt.test.js +++ b/test/oplog/crdt.test.js @@ -18,35 +18,31 @@ Object.keys(testAPIs).forEach((IPFS) => { describe('Log - CRDT (' + IPFS + ')', function () { this.timeout(config.timeout) - const { identityKeyFixtures, signingKeyFixtures, identityKeysPath, signingKeysPath } = config + const { identityKeyFixtures, signingKeyFixtures, identityKeysPath } = config - let keystore, signingKeyStore + let keystore let identities1, identities2, identities3 before(async () => { rmrf(identityKeysPath) - rmrf(signingKeysPath) await copy(identityKeyFixtures, identityKeysPath) - await copy(signingKeyFixtures, signingKeysPath) + await copy(signingKeyFixtures, identityKeysPath) keystore = new KeyStore(identityKeysPath) - signingKeyStore = new KeyStore(signingKeysPath) const storage = await MemoryStorage() - identities1 = await Identities({ keystore, signingKeyStore, storage }) - identities2 = await Identities({ keystore, signingKeyStore, storage }) - identities3 = await Identities({ keystore, signingKeyStore, storage }) + identities1 = await Identities({ keystore, storage }) + identities2 = await Identities({ keystore, storage }) + identities3 = await Identities({ keystore, storage }) testIdentity = await identities1.createIdentity({ id: 'userA' }) testIdentity2 = await identities2.createIdentity({ id: 'userB' }) testIdentity3 = await identities3.createIdentity({ id: 'userC' }) }) after(async () => { - await signingKeyStore.close() await keystore.close() rmrf(identityKeysPath) - rmrf(signingKeysPath) }) describe('is a CRDT', async () => { diff --git a/test/oplog/entry.test.js b/test/oplog/entry.test.js index 7ec4867..99354ee 100644 --- a/test/oplog/entry.test.js +++ b/test/oplog/entry.test.js @@ -16,9 +16,9 @@ Object.keys(testAPIs).forEach((IPFS) => { describe('Entry (' + IPFS + ')', function () { this.timeout(config.timeout) - const { identityKeyFixtures, signingKeyFixtures, identityKeysPath, signingKeysPath } = config + const { identityKeyFixtures, signingKeyFixtures, identityKeysPath } = config - let keystore, signingKeyStore, ipfsBlockStore, identityStore + let keystore, ipfsBlockStore, identityStore let identities let testIdentity let ipfsd, ipfs @@ -28,26 +28,22 @@ Object.keys(testAPIs).forEach((IPFS) => { ipfs = ipfsd.api await copy(identityKeyFixtures, identityKeysPath) - await copy(signingKeyFixtures, signingKeysPath) + await copy(signingKeyFixtures, identityKeysPath) keystore = new KeyStore(identityKeysPath) - signingKeyStore = new KeyStore(signingKeysPath) - identities = await Identities({ keystore, signingKeyStore, ipfs }) + identities = await Identities({ keystore, ipfs }) testIdentity = await identities.createIdentity({ id: 'userA' }) }) after(async () => { - await copy(identityKeyFixtures, identityKeysPath) - await copy(signingKeyFixtures, signingKeysPath) - rmrf(identityKeysPath) - rmrf(signingKeysPath) await keystore.close() - await signingKeyStore.close() if (ipfsd) { await stopIpfs(ipfsd) } + + rmrf(identityKeysPath) }) describe('create', () => { diff --git a/test/oplog/heads.test.js b/test/oplog/heads.test.js index 2b4d050..516784b 100644 --- a/test/oplog/heads.test.js +++ b/test/oplog/heads.test.js @@ -22,31 +22,27 @@ Object.keys(testAPIs).forEach((IPFS) => { describe('Log - Heads (' + IPFS + ')', function () { this.timeout(config.timeout) - const { identityKeyFixtures, signingKeyFixtures, identityKeysPath, signingKeysPath } = config + const { identityKeyFixtures, signingKeyFixtures, identityKeysPath } = config - let keystore, signingKeyStore + let keystore let identities before(async () => { rmrf(identityKeysPath) - rmrf(signingKeysPath) + await copy(identityKeyFixtures, identityKeysPath) - await copy(signingKeyFixtures, signingKeysPath) + await copy(signingKeyFixtures, identityKeysPath) keystore = new KeyStore(identityKeysPath) - signingKeyStore = new KeyStore(signingKeysPath) const storage = await MemoryStorage() - identities = await Identities({ keystore, signingKeyStore, storage }) + identities = await Identities({ keystore, storage }) testIdentity = await identities.createIdentity({ id: 'userA' }) }) after(async () => { - rmrf(identityKeysPath) - rmrf(signingKeysPath) - await keystore.close() - await signingKeyStore.close() + rmrf(identityKeysPath) }) it('finds one head after one entry', async () => { diff --git a/test/oplog/iterator.test.js b/test/oplog/iterator.test.js index cf5d904..7b9035c 100644 --- a/test/oplog/iterator.test.js +++ b/test/oplog/iterator.test.js @@ -21,7 +21,7 @@ Object.keys(testAPIs).forEach((IPFS) => { let ipfs let ipfsd - let keystore, signingKeyStore + let keystore let identities1, identities2, identities3 let testIdentity, testIdentity2, testIdentity3 @@ -31,18 +31,15 @@ Object.keys(testAPIs).forEach((IPFS) => { for (const [key, value] of Object.entries(identityKeys)) { await keystore.addKey(key, value) } - - signingKeyStore = new KeyStore('./keys_2') - await signingKeyStore.open() for (const [key, value] of Object.entries(signingKeys)) { - await signingKeyStore.addKey(key, value) + await keystore.addKey(key, value) } const storage = await MemoryStorage() - identities1 = await Identities({ keystore, signingKeyStore, storage }) - identities2 = await Identities({ keystore, signingKeyStore, storage }) - identities3 = await Identities({ keystore, signingKeyStore, storage }) + identities1 = await Identities({ keystore, storage }) + identities2 = await Identities({ keystore, storage }) + identities3 = await Identities({ keystore, storage }) testIdentity = await identities1.createIdentity({ id: 'userA' }) testIdentity2 = await identities2.createIdentity({ id: 'userB' }) testIdentity3 = await identities3.createIdentity({ id: 'userC' }) @@ -58,11 +55,7 @@ Object.keys(testAPIs).forEach((IPFS) => { if (keystore) { await keystore.close() } - if (signingKeyStore) { - await signingKeyStore.close() - } rmrf('./keys_1') - rmrf('./keys_2') }) describe('Basic iterator functionality', async () => { diff --git a/test/oplog/join-concurrent.test.js b/test/oplog/join-concurrent.test.js index e873784..ae9da17 100644 --- a/test/oplog/join-concurrent.test.js +++ b/test/oplog/join-concurrent.test.js @@ -18,33 +18,30 @@ Object.keys(testAPIs).forEach(IPFS => { describe('Log - Join Concurrent Entries (' + IPFS + ')', function () { this.timeout(config.timeout) - const { identityKeyFixtures, signingKeyFixtures, identityKeysPath, signingKeysPath } = config + const { identityKeyFixtures, signingKeyFixtures, identityKeysPath } = config - let keystore, signingKeyStore + let keystore let identities1, identities2 before(async () => { rmrf(identityKeysPath) - rmrf(signingKeysPath) + await copy(identityKeyFixtures, identityKeysPath) - await copy(signingKeyFixtures, signingKeysPath) + await copy(signingKeyFixtures, identityKeysPath) keystore = new KeyStore(identityKeysPath) - signingKeyStore = new KeyStore(signingKeysPath) const storage = await MemoryStorage() - identities1 = await Identities({ keystore, signingKeyStore, storage }) - identities2 = await Identities({ keystore, signingKeyStore, storage }) + identities1 = await Identities({ keystore, storage }) + identities2 = await Identities({ keystore, storage }) testIdentity = await identities1.createIdentity({ id: 'userA' }) testIdentity2 = await identities2.createIdentity({ id: 'userB' }) }) after(async () => { await keystore.close() - await signingKeyStore.close() rmrf(identityKeysPath) - rmrf(signingKeysPath) }) describe('join ', async () => { diff --git a/test/oplog/join.test.js b/test/oplog/join.test.js index 9f20aba..6b86aea 100644 --- a/test/oplog/join.test.js +++ b/test/oplog/join.test.js @@ -20,7 +20,7 @@ Object.keys(testAPIs).forEach((IPFS) => { describe('Log - Join (' + IPFS + ')', async function () { this.timeout(config.timeout) - let keystore, signingKeyStore + let keystore let log1, log2, log3, log4 let identities1, identities2, identities3, identities4 let testIdentity, testIdentity2, testIdentity3, testIdentity4 @@ -31,19 +31,16 @@ Object.keys(testAPIs).forEach((IPFS) => { for (const [key, value] of Object.entries(identityKeys)) { await keystore.addKey(key, value) } - - signingKeyStore = new KeyStore('./keys_2') - await signingKeyStore.open() for (const [key, value] of Object.entries(signingKeys)) { - await signingKeyStore.addKey(key, value) + await keystore.addKey(key, value) } const storage = await MemoryStorage() - identities1 = await Identities({ keystore, signingKeyStore, storage }) - identities2 = await Identities({ keystore, signingKeyStore, storage }) - identities3 = await Identities({ keystore, signingKeyStore, storage }) - identities4 = await Identities({ keystore, signingKeyStore, storage }) + identities1 = await Identities({ keystore, storage }) + identities2 = await Identities({ keystore, storage }) + identities3 = await Identities({ keystore, storage }) + identities4 = await Identities({ keystore, storage }) testIdentity = await identities1.createIdentity({ id: 'userC' }) testIdentity2 = await identities2.createIdentity({ id: 'userB' }) testIdentity3 = await identities3.createIdentity({ id: 'userD' }) @@ -54,11 +51,7 @@ Object.keys(testAPIs).forEach((IPFS) => { if (keystore) { await keystore.close() } - if (signingKeyStore) { - await signingKeyStore.close() - } rmrf('./keys_1') - rmrf('./keys_2') }) beforeEach(async () => { diff --git a/test/oplog/load.test.js b/test/oplog/load.test.js index 52f5ce0..80efc98 100644 --- a/test/oplog/load.test.js +++ b/test/oplog/load.test.js @@ -32,7 +32,7 @@ Object.keys(testAPIs).forEach((IPFS) => { describe.skip('Log - Load (' + IPFS + ')', function () { this.timeout(config.timeout) - const { identityKeyFixtures, signingKeyFixtures, identityKeysPath, signingKeysPath } = config + const { identityKeyFixtures, signingKeyFixtures, identityKeysPath } = config const firstWriteExpectedData = [ 'entryA6', 'entryA7', 'entryA8', 'entryA9', @@ -41,21 +41,20 @@ Object.keys(testAPIs).forEach((IPFS) => { 'entryA3', 'entryA4', 'entryA5', 'entryC0' ] - let keystore, signingKeyStore + let keystore before(async () => { rmrf(identityKeysPath) - rmrf(signingKeysPath) + await copy(identityKeyFixtures, identityKeysPath) - await copy(signingKeyFixtures, signingKeysPath) + await copy(signingKeyFixtures, identityKeysPath) keystore = new KeyStore(identityKeysPath) - signingKeyStore = new KeyStore(signingKeysPath) - testIdentity = await createIdentity({ id: 'userC', keystore, signingKeyStore }) - testIdentity2 = await createIdentity({ id: 'userB', keystore, signingKeyStore }) - testIdentity3 = await createIdentity({ id: 'userD', keystore, signingKeyStore }) - testIdentity4 = await createIdentity({ id: 'userA', keystore, signingKeyStore }) + testIdentity = await createIdentity({ id: 'userC', keystore }) + testIdentity2 = await createIdentity({ id: 'userB', keystore }) + testIdentity3 = await createIdentity({ id: 'userD', keystore }) + testIdentity4 = await createIdentity({ id: 'userA', keystore }) ipfsd = await startIpfs(IPFS, config.defaultIpfsConfig) ipfs = ipfsd.api @@ -66,11 +65,8 @@ Object.keys(testAPIs).forEach((IPFS) => { after(async () => { await stopIpfs(ipfsd) - rmrf(identityKeysPath) - rmrf(signingKeysPath) - await keystore.close() - await signingKeyStore.close() + rmrf(identityKeysPath) }) describe('fromJSON', async () => { diff --git a/test/oplog/log.test.js b/test/oplog/log.test.js index 8d10978..f469a6b 100644 --- a/test/oplog/log.test.js +++ b/test/oplog/log.test.js @@ -19,30 +19,26 @@ Object.keys(testAPIs).forEach((IPFS) => { describe('Log (' + IPFS + ')', function () { this.timeout(config.timeout) - const { identityKeyFixtures, signingKeyFixtures, identityKeysPath, signingKeysPath } = config + const { identityKeyFixtures, signingKeyFixtures, identityKeysPath } = config - let keystore, signingKeyStore + let keystore let identities before(async () => { await copy(identityKeyFixtures, identityKeysPath) - await copy(signingKeyFixtures, signingKeysPath) + await copy(signingKeyFixtures, identityKeysPath) keystore = new KeyStore(identityKeysPath) - signingKeyStore = new KeyStore(signingKeysPath) const storage = await MemoryStorage() - identities = await Identities({ keystore, signingKeyStore, storage }) + identities = await Identities({ keystore, storage }) testIdentity = await identities.createIdentity({ id: 'userA' }) }) after(async () => { - rmrf(signingKeysPath) - rmrf(identityKeysPath) - await keystore.close() - await signingKeyStore.close() + rmrf(identityKeysPath) }) describe('create', async () => { diff --git a/test/oplog/references.test.js b/test/oplog/references.test.js index 3e028ca..a12416d 100644 --- a/test/oplog/references.test.js +++ b/test/oplog/references.test.js @@ -18,32 +18,28 @@ Object.keys(testAPIs).forEach((IPFS) => { describe('Log - References (' + IPFS + ')', function () { this.timeout(config.timeout) - const { identityKeyFixtures, signingKeyFixtures, identityKeysPath, signingKeysPath } = config + const { identityKeyFixtures, signingKeyFixtures, identityKeysPath } = config let keystore, signingKeyStore let identities before(async () => { rmrf(identityKeysPath) - rmrf(signingKeysPath) + await copy(identityKeyFixtures, identityKeysPath) - await copy(signingKeyFixtures, signingKeysPath) + await copy(signingKeyFixtures, identityKeysPath) keystore = new KeyStore(identityKeysPath) - signingKeyStore = new KeyStore(signingKeysPath) const storage = await MemoryStorage() - identities = await Identities({ keystore, signingKeyStore, storage }) + identities = await Identities({ keystore, storage }) testIdentity = await identities.createIdentity({ id: 'userA' }) }) after(async () => { - rmrf(identityKeysPath) - rmrf(signingKeysPath) - await keystore.close() - await signingKeyStore.close() + rmrf(identityKeysPath) }) describe('References', async () => { diff --git a/test/oplog/replicate.test.js b/test/oplog/replicate.test.js index 2e0df06..62d72d3 100644 --- a/test/oplog/replicate.test.js +++ b/test/oplog/replicate.test.js @@ -16,8 +16,6 @@ Object.keys(testAPIs).forEach((IPFS) => { describe('ipfs-log - Replication (' + IPFS + ')', function () { this.timeout(config.timeout * 2) - const { identityKeyFixtures, signingKeyFixtures, identityKeysPath, signingKeysPath } = config - let ipfsd1, ipfsd2 let ipfs1, ipfs2 let id1, id2 @@ -27,11 +25,6 @@ Object.keys(testAPIs).forEach((IPFS) => { let storage1, storage2 before(async () => { - rmrf(identityKeysPath) - rmrf(signingKeysPath) - await copy(identityKeyFixtures, identityKeysPath) - await copy(signingKeyFixtures, signingKeysPath) - // Start two IPFS instances ipfsd1 = await startIpfs(IPFS, config.daemon1) ipfsd2 = await startIpfs(IPFS, config.daemon2) diff --git a/test/oplog/signed-log.test.js b/test/oplog/signed-log.test.js index 8803203..691970f 100644 --- a/test/oplog/signed-log.test.js +++ b/test/oplog/signed-log.test.js @@ -5,7 +5,7 @@ import { Identities } from '../../src/identities/index.js' // Test utils import { config, testAPIs } from 'orbit-db-test-utils' -import { identityKeys, signingKeys, createTestIdentities, cleanUpTestIdentities } from '../fixtures/orbit-db-identity-keys.js' +import { createTestIdentities, cleanUpTestIdentities } from '../fixtures/orbit-db-identity-keys.js' const { sync: rmrf } = rimraf const { createIdentity } = Identities diff --git a/test/storage.spec.js b/test/storage.spec.js index 54e465a..b41d9aa 100644 --- a/test/storage.spec.js +++ b/test/storage.spec.js @@ -17,17 +17,16 @@ Object.keys(testAPIs).forEach((_) => { describe('Storages (' + _ + ')', function () { this.timeout(config.timeout) - const { identityKeyFixtures, signingKeyFixtures, identityKeysPath, signingKeysPath } = config + const { identityKeyFixtures, signingKeyFixtures, identityKeysPath } = config let ipfs1 - let keystore, signingKeyStore + let keystore let testIdentity1 before(async () => { rmrf(identityKeysPath) - rmrf(signingKeysPath) await copy(identityKeyFixtures, identityKeysPath) - await copy(signingKeyFixtures, signingKeysPath) + await copy(signingKeyFixtures, identityKeysPath) rmrf('./ipfs1') await copy('./test/fixtures/ipfs1', './ipfs1') @@ -36,10 +35,9 @@ Object.keys(testAPIs).forEach((_) => { ipfs1 = await IPFS.create({ ...config.daemon1, repo: './ipfs1' }) keystore = new KeyStore(identityKeysPath) - signingKeyStore = new KeyStore(signingKeysPath) const storage = await MemoryStorage() - const identities = await Identities({ keystore, signingKeyStore, storage }) + const identities = await Identities({ keystore, storage }) testIdentity1 = await identities.createIdentity({ id: 'userA' }) }) @@ -50,13 +48,10 @@ Object.keys(testAPIs).forEach((_) => { if (keystore) { await keystore.close() } - if (signingKeyStore) { - await signingKeyStore.close() - } rmrf(identityKeysPath) - rmrf(signingKeysPath) rmrf(testIdentity1.id) rmrf('./ipfs1') + rmrf('./orbitdb') }) const runTestWithStorage = async (storage) => { From 0b385e5c57a10dc9886f415be2046c734b489bab Mon Sep 17 00:00:00 2001 From: haad Date: Mon, 20 Feb 2023 11:38:20 +0200 Subject: [PATCH 6/6] Clean ups --- src/identities/identities.js | 5 ++-- src/identities/identity.js | 29 +++++----------------- src/identities/providers/did.js | 35 ++++++++++++++++++--------- src/identities/providers/ethereum.js | 28 +++++++++++++++------ src/identities/providers/interface.js | 2 +- src/identities/providers/orbitdb.js | 26 +++++++++----------- src/oplog/entry.js | 2 +- test/identities/identity.test.js | 8 +++--- 8 files changed, 70 insertions(+), 65 deletions(-) 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 () => {