orbitdb/test/identities/identities.test.js
2023-03-01 14:49:00 +02:00

343 lines
11 KiB
JavaScript

import assert from 'assert'
import path from 'path'
import rmrf from 'rimraf'
import LevelStorage from '../../src/storage/level.js'
import KeyStore, { signMessage, verifyMessage } from '../../src/key-store.js'
import Identities, { addIdentityProvider } from '../../src/identities/identities.js'
import Identity from '../../src/identities/identity.js'
import fs from 'fs-extra'
const fixturesPath = path.resolve('./test/identities/fixtures/keys')
const savedKeysPath = path.resolve('./test/identities/fixtures/savedKeys')
const identityKeysPath = path.resolve('./test/identities/identityKeys')
import testKeysPath from '../fixtures/test-keys-path.js '
const type = 'orbitdb'
describe('Identities', function () {
before(async () => {
rmrf.sync(identityKeysPath)
})
after(async () => {
rmrf.sync(identityKeysPath)
})
describe('Creating Identities', () => {
const id = 'userA'
let identities
let identity
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)
})
})
describe('Get Identity', () => {
const id = 'userA'
let identities
let identity
afterEach(async () => {
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.skip('Passing in custom keystore', async () => {
const id = 'userB'
let identity
let identities
let keystore
before(async () => {
keystore = await KeyStore({ path: testKeysPath })
identities = await Identities({ keystore })
})
after(async () => {
if (keystore) {
await keystore.close()
}
})
it('has the correct id', async () => {
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)
})
it('created a key for id in identity-keystore', async () => {
const key = await keystore.getKey(id)
assert.notStrictEqual(key, undefined)
})
it('has the correct public key', async () => {
const key = await keystore.getKey(id)
const externalId = Buffer.from(key.public.marshal()).toString('hex')
const signingKey = await keystore.getKey(externalId)
assert.notStrictEqual(signingKey, undefined)
assert.strictEqual(identity.publicKey, keystore.getPublic(signingKey))
})
it('has a signature for the id', async () => {
const key = await keystore.getKey(id)
const externalId = Buffer.from(key.public.marshal()).toString('hex')
const signingKey = await keystore.getKey(externalId)
const idSignature = await signMessage(signingKey, externalId)
const publicKey = Buffer.from(signingKey.public.marshal()).toString('hex')
const verifies = await verifyMessage(idSignature, publicKey, externalId)
assert.strictEqual(verifies, true)
assert.strictEqual(identity.signatures.id, idSignature)
})
it('has a signature for the publicKey', async () => {
const key = await keystore.getKey(id)
const externalId = Buffer.from(key.public.marshal()).toString('hex')
const signingKey = await keystore.getKey(externalId)
const idSignature = await signMessage(signingKey, externalId)
const externalKey = await keystore.getKey(id)
const publicKeyAndIdSignature = await signMessage(externalKey, identity.publicKey + idSignature)
assert.strictEqual(identity.signatures.publicKey, publicKeyAndIdSignature)
})
})
describe('create an identity with saved keys', () => {
const id = 'userX'
const expectedPublicKey = '0442fa42a69135eade1e37ea520bc8ee9e240efd62cb0edf0516b21258b4eae656241c40da462c95189b1ade83419138ca59845beb90d29b1be8542bde388ca5f9'
const expectedIdSignature = '3044022068b4bc360d127e39164fbc3b5184f5bd79cc5976286f793d9b38d1f2818e0259022027b875dc8c73635b32db72177b9922038ec4b1eabc8f1fd0919806b0b2519419'
const expectedPkIdSignature = '304402206d1aeff3a874b7bd83300219badf68bbcb514e2c60a7b40cec5f78ff2b7ba0f20220085f5f138730603418a0570ba12720f0a46997527bb4a077cd26b545e7811c31'
let identities
let identity
let savedKeysKeyStore
before(async () => {
savedKeysKeyStore = await KeyStore({ path: testKeysPath })
identities = await Identities({ keystore: savedKeysKeyStore })
identity = await identities.createIdentity({ id })
})
after(async () => {
if (identities) {
await identities.keystore.close()
}
rmrf.sync(savedKeysPath)
})
it('has the correct id', async () => {
const key = await savedKeysKeyStore.getKey(id)
assert.strictEqual(identity.id, Buffer.from(key.public.marshal()).toString('hex'))
})
it('has the correct public key', async () => {
assert.strictEqual(identity.publicKey, expectedPublicKey)
})
it('has the correct identity type', async () => {
assert.strictEqual(identity.type, type)
})
it('has the correct idSignature', async () => {
assert.strictEqual(identity.signatures.id, expectedIdSignature)
})
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 signMessage(internalSigningKey, identity.id)
const publicKeyAndIdSignature = await signMessage(externalSigningKey, identity.publicKey + idSignature)
const expectedSignature = { id: idSignature, publicKey: publicKeyAndIdSignature }
assert.deepStrictEqual(identity.signatures, expectedSignature)
})
})
describe('verify identity\'s signature', () => {
const id = 'QmFoo'
let identities
let identity
let keystore
before(async () => {
keystore = await KeyStore({ path: testKeysPath })
})
after(async () => {
if (keystore) {
await keystore.close()
}
})
it('identity pkSignature verifies', async () => {
identities = await Identities({ keystore })
identity = await identities.createIdentity({ id, type })
const verified = await verifyMessage(identity.signatures.id, identity.publicKey, identity.id)
assert.strictEqual(verified, true)
})
it('identity signature verifies', async () => {
identities = await Identities({ keystore })
identity = await identities.createIdentity({ id, type })
const verified = await verifyMessage(identity.signatures.publicKey, identity.id, identity.publicKey + identity.signatures.id)
assert.strictEqual(verified, true)
})
it('false signature doesn\'t verify', async () => {
class IP {
async getId () { return 'pubKey' }
async signIdentity (data) { return `false signature '${data}'` }
static async verifyIdentity (data) { return false }
static get type () { return 'fake' }
}
addIdentityProvider(IP)
identity = await identities.createIdentity({ type: IP.type })
const verified = await identities.verifyIdentity(identity)
assert.strictEqual(verified, false)
})
})
describe('verify identity', () => {
const id = 'QmFoo'
let identities
let identity
let keystore
before(async () => {
keystore = await KeyStore({ path: testKeysPath })
identities = await Identities({ keystore })
})
after(async () => {
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 identities
let identity
let keystore
before(async () => {
keystore = await KeyStore({ path: testKeysPath })
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 signMessage(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 { publicKey, signatures, type } = identity
const modifiedIdentity = await Identity({ id: 'this id does not exist', publicKey, signatures, type })
let signature
let err
try {
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')
})
})
describe('verify data signed by an identity', () => {
const id = '03602a3da3eb35f1148e8028f141ec415ef7f6d4103443edbfec2a0711d716f53f'
const data = 'hello friend'
let identities
let identity
let keystore
let signature
before(async () => {
keystore = await KeyStore({ path: testKeysPath })
})
after(async () => {
if (keystore) {
await keystore.close()
}
})
beforeEach(async () => {
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 identities.verify(signature, identity.publicKey, data)
assert.strictEqual(verified, true)
})
it('doesn\'t verify invalid signature', async () => {
const verified = await identities.verify('invalid', identity.publicKey, data)
assert.strictEqual(verified, false)
})
})
})