Merge pull request #9 from orbitdb/refactor/identity-provider

Refactor IdentityProvider
This commit is contained in:
Haad 2023-02-20 12:15:51 +02:00 committed by GitHub
commit 4c40f6947f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
45 changed files with 1035 additions and 960 deletions

6
.gitignore vendored
View File

@ -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
.vscode

View File

@ -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

View File

@ -0,0 +1,140 @@
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 { LRUStorage, IPFSBlockStorage, MemoryStorage } 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, identityKeysPath, storage, ipfs } = {}) => {
keystore = keystore || new KeyStore(identityKeysPath || DefaultIdentityKeysPath)
storage = storage || (ipfs ? await IPFSBlockStorage({ ipfs, pin: true }) : await MemoryStorage())
const verifiedIdentitiesCache = await LRUStorage({ size: 1000 })
const getIdentity = async (hash) => {
const bytes = await storage.get(hash)
if (bytes) {
return decodeIdentity(bytes)
}
}
const createIdentity = async (options = {}) => {
options.keystore = 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 publicKeyAndIdSignature = await identityProvider.signIdentity(publicKey + idSignature, options)
const signatures = {
id: idSignature,
publicKey: publicKeyAndIdSignature
}
const identity = await Identity({ id, publicKey, signatures, type, sign, verify })
await storage.put(identity.hash, identity.bytes)
return identity
}
const verifyIdentity = async (identity) => {
if (!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 isEqual(identity, verifiedIdentity)
}
const Provider = getProviderFor(identity.type)
const identityVerified = await Provider.verifyIdentity(identity)
if (identityVerified) {
await verifiedIdentitiesCache.put(signatures.id, identity)
}
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)
}
return {
createIdentity,
verifyIdentity,
getIdentity,
sign,
verify,
keystore
}
}
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
}

View File

@ -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 }

View File

@ -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

View File

@ -1,94 +1,80 @@
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, provider) {
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')
}
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 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')
if (!isDefined(idSignature)) {
throw new Error('Signature of the id (idSignature) is required')
}
signatures = Object.assign({}, signatures)
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
const identity = {
id,
publicKey,
signatures,
type,
sign,
verify
}
async store () {
const value = this.toJSON()
this.hash = await this._provider._storage.put(value)
}
const { hash, bytes } = await _encodeIdentity(identity)
identity.hash = hash
identity.bytes = bytes
/**
* 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 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
}
}
return identity
}
export default Identity
/**
* 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 }

View File

@ -1,2 +1,12 @@
export { default as IdentityProvider } from './identity-provider.js'
export { default as Identity } from './identity.js'
export {
default as Identities,
addIdentityProvider,
removeIdentityProvider,
isProviderSupported
} from './identities.js'
export {
default as Identity,
isIdentity,
isEqual
} from './identity.js'

View File

@ -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
}
}

View File

@ -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()
}
}

View File

@ -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
*/

View File

@ -1,51 +1,47 @@
import IdentityProvider from './interface.js'
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')
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`)
}
return keystore.sign(key, data)
return KeyStore.sign(key, data)
}
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)
}
}

View File

@ -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'

View File

@ -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
}

View File

@ -7,7 +7,7 @@ import { isDefined } from '../utils/index.js'
/*
* @description
* An ipfs-log entry
* A Log entry
*/
const codec = dagCbor
@ -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
@ -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)
}
/**

View File

@ -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}"`)
}

View File

@ -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'
@ -10,10 +9,9 @@ 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
const { createIdentity } = IdentityProvider
const OpLog = { Log, Entry, IPFSBlockStorage, LevelStorage }
@ -23,8 +21,9 @@ 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
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)
@ -85,18 +86,12 @@ Object.keys(testAPIs).forEach((IPFS) => {
if (keystore) {
await keystore.close()
}
if (signingKeyStore) {
await signingKeyStore.close()
}
if (testIdentity1) {
rmrf(testIdentity1.id)
}
if (testIdentity2) {
rmrf(testIdentity2.id)
}
rmrf('./orbitdb')
rmrf('./keys_1')
rmrf('./keys_2')
})
describe('using database', () => {

View File

@ -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'
@ -10,10 +10,10 @@ 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 } = IdentityProvider
const { createIdentity } = Identities
const OpLog = { Log, Entry, IPFSBlockStorage, LevelStorage }
@ -23,13 +23,22 @@ 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
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)
@ -74,18 +85,12 @@ Object.keys(testAPIs).forEach((IPFS) => {
if (keystore) {
await keystore.close()
}
if (signingKeyStore) {
await signingKeyStore.close()
}
if (testIdentity1) {
rmrf(testIdentity1.id)
}
if (testIdentity2) {
rmrf(testIdentity2.id)
}
rmrf('./orbitdb')
rmrf('./keys_1')
rmrf('./keys_2')
})
describe('using database', () => {
@ -93,13 +98,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 +202,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
}

View File

@ -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'
@ -10,10 +10,10 @@ 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 } = IdentityProvider
const { createIdentity } = Identities
const OpLog = { Log, Entry, IPFSBlockStorage, LevelStorage }
Object.keys(testAPIs).forEach((IPFS) => {
@ -22,13 +22,22 @@ 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
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)
@ -73,18 +84,12 @@ Object.keys(testAPIs).forEach((IPFS) => {
if (keystore) {
await keystore.close()
}
if (signingKeyStore) {
await signingKeyStore.close()
}
if (testIdentity1) {
rmrf(testIdentity1.id)
}
if (testIdentity2) {
rmrf(testIdentity2.id)
}
rmrf('./orbitdb')
rmrf('./keys_1')
rmrf('./keys_2')
})
describe('using database', () => {
@ -92,13 +97,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 +200,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
}

View File

@ -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" }
@ -31,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()
@ -39,47 +37,25 @@ 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)
}
// 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]
}
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 })
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' })
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()
}
rmrf('./keys_1')
rmrf('./orbitdb')
}
export {

View File

@ -1 +0,0 @@
MANIFEST-000031

View File

@ -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

View File

@ -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

View File

@ -1,28 +1,34 @@
import assert from 'assert'
import path from 'path'
import rmrf from 'rimraf'
import { KeyStore, IdentityProvider } from '../../src/index.js'
import { Identity } from '../../src/identities/index.js'
import { KeyStore, Identities } from '../../src/index.js'
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/identies/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 () => {
DIDIdentityProvider.setDIDResolver(KeyDidResolver.getResolver())
IdentityProvider.addIdentityProvider(DIDIdentityProvider)
keystore = new KeyStore(keypath)
keystore = new KeyStore()
await keystore.open()
DIDIdentityProvider.setDIDResolver(KeyDidResolver.getResolver())
addIdentityProvider(DIDIdentityProvider)
identities = await Identities({ keystore })
})
after(async () => {
await keystore.close()
if (keystore) {
await keystore.close()
}
rmrf.sync('./keystore')
rmrf.sync('./orbitdb')
})
describe('create an DID identity', () => {
@ -30,7 +36,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 +56,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 +64,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 +74,23 @@ 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 { publicKey, signatures, type } = identity
const identity2 = await Identity({
id: 'NotAnId',
publicKey,
signatures,
type
})
const verified = await identities.verifyIdentity(identity2)
assert.strictEqual(verified, false)
})
})
@ -89,23 +101,32 @@ 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)
})
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, '<sig>', identity.signatures, identity.type, identity.provider)
const { publicKey, signatures, type } = identity
const modifiedIdentity = await Identity({
id: 'this id does not exist',
publicKey,
signatures: {
id: '<sig>',
publicKey: signatures.publicKey
},
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()
}
@ -120,17 +141,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)
})
})

View File

@ -1,23 +1,29 @@
import assert from 'assert'
import path from 'path'
import rmrf from 'rimraf'
import { KeyStore, IdentityProvider } from '../../src/index.js'
import { Identity } from '../../src/identities/index.js'
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 () => {
IdentityProvider.addIdentityProvider(EthIdentityProvider)
keystore = new KeyStore(keypath)
keystore = new KeyStore()
await keystore.open()
addIdentityProvider(EthIdentityProvider)
identities = await Identities({ keystore })
})
after(async () => {
await keystore.close()
if (keystore) {
await keystore.close()
}
rmrf.sync('./keystore')
rmrf.sync('./orbitdb')
})
describe('create an ethereum identity', () => {
@ -27,7 +33,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 +53,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 +61,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 +71,23 @@ 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 { publicKey, signatures, type } = identity
const identity2 = await Identity({
id: 'NotAnId',
publicKey,
signatures,
type
})
const verified = await identities.verifyIdentity(identity2)
assert.strictEqual(verified, false)
})
})
@ -85,23 +97,32 @@ 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)
})
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, '<sig>', identity.signatures, identity.type, identity.provider)
const { publicKey, signatures, type } = identity
const modifiedIdentity = await Identity({
id: 'this id does not exist',
publicKey,
signatures: {
id: '<sig>',
publicKey: signatures.publicKey,
},
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()
}
@ -115,17 +136,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)
})
})

View File

@ -1,63 +1,92 @@
import assert from 'assert'
import path from 'path'
import rmrf from 'rimraf'
import { KeyStore, IdentityProvider } from '../../src/index.js'
import { Identity } from '../../src/identities/index.js'
import { KeyStore, Identities } from '../../src/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')
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)
})
after(async () => {
rmrf.sync(signingKeysPath)
rmrf.sync(identityKeysPath)
})
describe('Creating IdentityProvider', () => {
describe('Creating Identities', () => {
const id = 'A'
let identities
let identity
it('identityKeysPath only - has the correct id', async () => {
identity = await IdentityProvider.createIdentity({ id, identityKeysPath })
const key = await identity.provider.keystore.getKey(id)
afterEach(async () => {
if (identities) {
await identities.keystore.close()
}
})
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 () => {
identity = await IdentityProvider.createIdentity({ id, identityKeysPath, signingKeysPath })
const key = await identity.provider.keystore.getKey(id)
const externalId = Buffer.from(key.public.marshal()).toString('hex')
assert.notStrictEqual(identity.id, externalId)
})
describe('Get Identity', () => {
const id = 'A'
let identities
let identity
afterEach(async () => {
await identity.provider.keystore.close()
await identity.provider.signingKeyStore.close()
if (identities) {
await identities.keystore.close()
}
})
it('gets the identity from storage', async () => {
identities = await Identities({ identityKeysPath })
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'; let identity; let keystore; let signingKeyStore
const id = 'B'
let identity
let identities
let keystore
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()
}
})
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 +110,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 +121,39 @@ 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()
}
rmrf.sync(savedKeysPath)
})
@ -147,44 +174,48 @@ 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)
})
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 expectedSignature = { id: idSignature, publicKey: pubKeyIdSignature }
const idSignature = await KeyStore.sign(internalSigningKey, identity.id)
const publicKeyAndIdSignature = await KeyStore.sign(externalSigningKey, identity.publicKey + idSignature)
const expectedSignature = { id: idSignature, publicKey: publicKeyAndIdSignature }
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
before(async () => {
keystore = new KeyStore(identityKeysPath)
await keystore.open()
signingKeyStore = new KeyStore(signingKeysPath)
await signingKeyStore.open()
})
after(async () => {
if (keystore) {
await keystore.close()
}
})
it('identity pkSignature verifies', async () => {
identity = await IdentityProvider.createIdentity({ id, type, 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 () => {
identity = await IdentityProvider.createIdentity({ id, type, 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)
})
@ -200,112 +231,117 @@ 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)
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
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 })
})
after(async () => {
await keystore.close()
await signingKeyStore.close()
if (keystore) {
await keystore.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
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 })
identity = await identities.createIdentity({ id })
})
after(async () => {
if (keystore) {
await keystore.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, '<sig>', identity.signatures, identity.type, identity.provider)
const { publicKey, signatures, type } = identity
const modifiedIdentity = await Identity({ id: 'this id does not exist', publicKey, signatures, 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 signature
before(async () => {
keystore = new KeyStore(identityKeysPath)
await keystore.open()
signingKeyStore = new KeyStore(signingKeysPath)
await signingKeyStore.open()
})
after(async () => {
if (keystore) {
await keystore.close()
}
})
beforeEach(async () => {
identity = await IdentityProvider.createIdentity({ id, type, keystore, signingKeyStore })
signature = await identity.provider.sign(identity, data, keystore)
identities = await Identities({ keystore })
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()
})
})
})

View File

@ -1,109 +0,0 @@
import assert from 'assert'
import { Identity } from '../../src/identities/index.js'
describe('Identity', function () {
const id = '0x01234567890abcdefghijklmnopqrstuvwxyz'
const publicKey = '<pubkey>'
const idSignature = 'signature for <id>'
const publicKeyAndIdSignature = 'signature for <publicKey + idSignature>'
const type = 'orbitdb'
const provider = 'IdentityProviderInstance'
let identity
before(async () => {
identity = new Identity(id, publicKey, idSignature, publicKeyAndIdSignature, type, provider)
})
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 = new 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 = new Identity('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 = new Identity('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 = new Identity('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 = new Identity('abc', publicKey, idSignature, publicKeyAndIdSignature, null, provider)
} catch (e) {
err = e.toString()
}
assert.strictEqual(err, 'Error: Identity type is required')
})
})
})

View File

@ -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 = '<pubkey>'
const signatures = {
id: 'signature for <id>',
publicKey: 'signature for <publicKey + idSignature>'
}
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 object 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 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+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: { publicKey: signatures.publicKey } })
} catch (e) {
err = e.toString()
}
assert.strictEqual(err, 'Error: Signature of 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)
})
})
})

View File

@ -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'
@ -10,10 +10,10 @@ 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 } = IdentityProvider
const { createIdentity } = Identities
const OpLog = { Log, Entry, IPFSBlockStorage, LevelStorage }
@ -23,13 +23,21 @@ 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
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)
@ -63,18 +73,12 @@ Object.keys(testAPIs).forEach((IPFS) => {
if (keystore) {
await keystore.close()
}
if (signingKeyStore) {
await signingKeyStore.close()
}
if (testIdentity1) {
rmrf(testIdentity1.id)
}
if (testIdentity2) {
rmrf(testIdentity2.id)
}
rmrf('./orbitdb')
rmrf('./keys_1')
rmrf('./keys_2')
})
afterEach(async () => {
@ -94,13 +98,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 +220,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
}

View File

@ -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
@ -18,29 +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()
testIdentity = await createIdentity({ id: 'userA', 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 () => {

View File

@ -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
@ -18,30 +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()
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, 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 () => {

View File

@ -2,24 +2,25 @@ 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) => {
describe('Entry (' + IPFS + ')', function () {
this.timeout(config.timeout)
const { identityKeyFixtures, signingKeyFixtures, identityKeysPath, signingKeysPath } = config
const { identityKeyFixtures, signingKeyFixtures, identityKeysPath } = config
let keystore, ipfsBlockStore, identityStore
let identities
let testIdentity
let keystore, signingKeyStore, ipfsBlockStore, identityStore
let ipfsd, ipfs
before(async () => {
@ -27,25 +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)
testIdentity = await createIdentity({ id: 'userA', 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', () => {
@ -76,11 +74,20 @@ Object.keys(testAPIs).forEach((IPFS) => {
// strictEqual(entry.hash, expectedHash)
})
it.skip('retrieves the identity from an entry', async() => {
const expected = testIdentity.toJSON()
it('retrieves the identity from an entry', async() => {
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 identityStore.get(entry.identity)
const entryIdentity = await identities.getIdentity(entry.identity)
deepStrictEqual(entryIdentity, expected)
})

View File

@ -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
@ -22,29 +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()
testIdentity = await createIdentity({ id: 'userA', 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 () => {

View File

@ -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) => {
@ -21,7 +21,8 @@ Object.keys(testAPIs).forEach((IPFS) => {
let ipfs
let ipfsd
let keystore, signingKeyStore
let keystore
let identities1, identities2, identities3
let testIdentity, testIdentity2, testIdentity3
before(async () => {
@ -30,18 +31,18 @@ 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()
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, 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' })
ipfsd = await startIpfs(IPFS, config.defaultIpfsConfig)
ipfs = ipfsd.api
@ -54,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 () => {

View File

@ -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
@ -18,30 +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()
testIdentity = await createIdentity({ id: 'userA', keystore, signingKeyStore, storage })
testIdentity2 = await createIdentity({ id: 'userB', 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 () => {

View File

@ -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]
@ -20,8 +20,9 @@ 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
before(async () => {
@ -30,30 +31,27 @@ 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()
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, 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' })
testIdentity4 = await identities4.createIdentity({ id: 'userA' })
})
after(async () => {
if (keystore) {
await keystore.close()
}
if (signingKeyStore) {
await signingKeyStore.close()
}
rmrf('./keys_1')
rmrf('./keys_2')
})
beforeEach(async () => {

View File

@ -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
@ -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 () => {

View File

@ -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
@ -19,28 +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()
testIdentity = await createIdentity({ id: 'userA', 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 () => {

View File

@ -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
@ -18,30 +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()
testIdentity = await createIdentity({ id: 'userA', 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 () => {

View File

@ -3,32 +3,28 @@ 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 KeyStore from '../../src/key-store.js'
import { Identities } from '../../src/identities/index.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
let ipfsd1, ipfsd2
let ipfs1, ipfs2
let id1, id2
const { identityKeyFixtures, signingKeyFixtures, identityKeysPath, signingKeysPath } = config
let keystore, signingKeyStore
let identities1, identities2
let testIdentity1, testIdentity2
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)
@ -41,27 +37,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 +90,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 +134,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)

View File

@ -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'
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('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
}
}

View File

@ -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,23 +11,22 @@ 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 () {
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,11 +35,10 @@ Object.keys(testAPIs).forEach((_) => {
ipfs1 = await IPFS.create({ ...config.daemon1, repo: './ipfs1' })
keystore = new KeyStore(identityKeysPath)
signingKeyStore = new KeyStore(signingKeysPath)
const storage = await MemoryStorage()
testIdentity1 = await createIdentity({ id: 'userA', keystore, signingKeyStore, storage })
const identities = await Identities({ keystore, storage })
testIdentity1 = await identities.createIdentity({ id: 'userA' })
})
after(async () => {
@ -50,14 +48,10 @@ Object.keys(testAPIs).forEach((_) => {
if (keystore) {
await keystore.close()
}
if (signingKeyStore) {
await signingKeyStore.close()
}
rmrf(identityKeysPath)
rmrf(signingKeysPath)
rmrf(testIdentity1.id)
rmrf('./orbitdb')
rmrf('./ipfs1')
rmrf('./orbitdb')
})
const runTestWithStorage = async (storage) => {