Clean ups

This commit is contained in:
haad 2023-02-20 11:38:20 +02:00
parent f84915fca8
commit 0b385e5c57
8 changed files with 70 additions and 65 deletions

View File

@ -44,6 +44,7 @@ const Identities = async ({ keystore, identityKeysPath, storage, ipfs } = {}) =>
id: idSignature, id: idSignature,
publicKey: publicKeyAndIdSignature publicKey: publicKeyAndIdSignature
} }
const identity = await Identity({ id, publicKey, signatures, type, sign, verify }) const identity = await Identity({ id, publicKey, signatures, type, sign, verify })
await storage.put(identity.hash, identity.bytes) await storage.put(identity.hash, identity.bytes)
@ -57,8 +58,8 @@ const Identities = async ({ keystore, identityKeysPath, storage, ipfs } = {}) =>
} }
const { id, publicKey, signatures } = identity const { id, publicKey, signatures } = identity
const idSignatureVerified = await KeyStore.verify(signatures.id, publicKey, id)
const idSignatureVerified = await KeyStore.verify(signatures.id, publicKey, id)
if (!idSignatureVerified) { if (!idSignatureVerified) {
return false return false
} }
@ -69,8 +70,8 @@ const Identities = async ({ keystore, identityKeysPath, storage, ipfs } = {}) =>
} }
const Provider = getProviderFor(identity.type) const Provider = getProviderFor(identity.type)
const identityVerified = await Provider.verifyIdentity(identity)
const identityVerified = await Provider.verifyIdentity(identity)
if (identityVerified) { if (identityVerified) {
await verifiedIdentitiesCache.put(signatures.id, identity) await verifiedIdentitiesCache.put(signatures.id, identity)
} }

View File

@ -9,29 +9,12 @@ const hasher = sha256
const hashStringEncoding = base58btc const hashStringEncoding = base58btc
const Identity = async ({ id, publicKey, signatures, type, sign, verify } = {}) => { const Identity = async ({ id, publicKey, signatures, type, sign, verify } = {}) => {
if (!isDefined(id)) { if (!isDefined(id)) throw new Error('Identity id is required')
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(publicKey)) { if (!isDefined(signatures.publicKey)) throw new Error('Signature of publicKey+id is required')
throw new Error('Invalid public key') if (!isDefined(type)) throw new Error('Identity type is required')
}
if (!isDefined(signatures)) {
throw new Error('Signatures is required')
}
if (!isDefined(signatures.id)) {
throw new Error('Signature of the id is required')
}
if (!isDefined(signatures.publicKey)) {
throw new Error('Signature of (publicKey + idSignature) is required')
}
if (!isDefined(type)) {
throw new Error('Identity type is required')
}
signatures = Object.assign({}, signatures) signatures = Object.assign({}, signatures)

View File

@ -2,32 +2,39 @@ import IdentityProvider from './interface.js'
import * as u8a from 'uint8arrays' import * as u8a from 'uint8arrays'
import { DID } from 'dids' import { DID } from 'dids'
const TYPE = 'DID' const type = 'DID'
class DIDIdentityProvider extends IdentityProvider { class DIDIdentityProvider extends IdentityProvider {
constructor ({ didProvider }) { constructor ({ didProvider }) {
super() super()
if (!didProvider) {
throw new Error('DIDIdentityProvider requires a didProvider parameter')
}
this.did = new DID({ this.did = new DID({
resolver: DIDIdentityProvider.did._resolver, resolver: DIDIdentityProvider.did._resolver,
provider: didProvider provider: didProvider
}) })
} }
static get type () { static get type () { return type }
return TYPE
}
async getId ({ space }) { async getId () {
if (!this.did.authenticated) await this.did.authenticate() if (!this.did.authenticated) {
await this.did.authenticate()
}
return this.did.id return this.did.id
} }
async signIdentity (data, { space }) { async signIdentity (data) {
if (!this.did.authenticated) await this.did.authenticate() if (!this.did.authenticated) {
await this.did.authenticate()
}
const payload = u8a.toString(u8a.fromString(data, 'base16'), 'base64url') 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 // 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) { static setDIDResolver (resolver) {
@ -42,15 +49,19 @@ class DIDIdentityProvider extends IdentityProvider {
if (!this.did) { if (!this.did) {
throw new Error('The DID resolver must first be set with setDIDResolver()') 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 { try {
const payload = u8a.toString(u8a.fromString(data, 'base16'), 'base64url') 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('.') const jws = [header, payload, signature].join('.')
await this.did.verifyJWS(jws) await this.did.verifyJWS(jws)
} catch (e) { } catch (e) {
return false return false
} }
return true return true
} }
} }

View File

@ -1,11 +1,12 @@
import IdentityProvider from './interface.js' import IdentityProvider from './interface.js'
import { Wallet, verifyMessage } from '@ethersproject/wallet' import { Wallet, verifyMessage } from '@ethersproject/wallet'
const type = 'ethereum' const type = 'ethereum'
class EthIdentityProvider extends IdentityProvider { class EthIdentityProvider extends IdentityProvider {
constructor (options = {}) { constructor ({ wallet } = {}) {
super() super()
this.wallet = options.wallet this.wallet = wallet
} }
// Returns the type of the identity provider // Returns the type of the identity provider
@ -20,16 +21,22 @@ class EthIdentityProvider extends IdentityProvider {
} }
// Returns a signature of pubkeysignature // Returns a signature of pubkeysignature
async signIdentity (data, options = {}) { async signIdentity (data) {
const wallet = this.wallet const wallet = this.wallet
if (!wallet) { throw new Error('wallet is required') }
if (!wallet) {
throw new Error('wallet is required')
}
return wallet.signMessage(data) return wallet.signMessage(data)
} }
static async verifyIdentity (identity) { static async verifyIdentity (identity) {
// Verify that identity was signed by the id // 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) return (signerAddress === identity.id)
} }
@ -38,17 +45,24 @@ class EthIdentityProvider extends IdentityProvider {
if (!options.mnemonicOpts.mnemonic) { if (!options.mnemonicOpts.mnemonic) {
throw new Error('mnemonic is required') 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) {
if (!options.encryptedJsonOpts.json) { if (!options.encryptedJsonOpts.json) {
throw new Error('encrypted json is required') throw new Error('encrypted json is required')
} }
if (!options.encryptedJsonOpts.password) { if (!options.encryptedJsonOpts.password) {
throw new Error('password for encrypted json is required') 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() 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 NOTE! This is the only property of the interface that
shouldn't be overridden in the inherited IdentityProvider shouldn't be overridden in the inherited IdentityProvider
*/ */

View File

@ -1,37 +1,36 @@
import IdentityProvider from './interface.js' import IdentityProvider from './interface.js'
import KeyStore from '../../key-store.js' import KeyStore from '../../key-store.js'
const type = 'orbitdb' const type = 'orbitdb'
class OrbitDBIdentityProvider extends IdentityProvider { class OrbitDBIdentityProvider extends IdentityProvider {
constructor ({ keystore }) { constructor ({ keystore }) {
super() super()
if (!keystore) { if (!keystore) {
throw new Error('OrbitDBIdentityProvider requires a keystore') throw new Error('OrbitDBIdentityProvider requires a keystore parameter')
} }
this._keystore = keystore this._keystore = keystore
} }
// Returns the type of the identity provider // Returns the type of the identity provider
static get type () { return type } static get type () { return type }
async getId (options = {}) { async getId ({ id } = {}) {
const id = options.id
if (!id) { if (!id) {
throw new Error('id is required') throw new Error('id is required')
} }
const key = await this._keystore.getKey(id) || await this._keystore.createKey(id)
const keystore = this._keystore
const key = await keystore.getKey(id) || await keystore.createKey(id)
return Buffer.from(key.public.marshal()).toString('hex') return Buffer.from(key.public.marshal()).toString('hex')
} }
async signIdentity (data, options = {}) { async signIdentity (data, { id } = {}) {
const id = options.id
if (!id) { if (!id) {
throw new Error('id is required') 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) { if (!key) {
throw new Error(`Signing key for '${id}' not found`) throw new Error(`Signing key for '${id}' not found`)
} }
@ -40,12 +39,9 @@ class OrbitDBIdentityProvider extends IdentityProvider {
} }
static async verifyIdentity (identity) { static async verifyIdentity (identity) {
const { id, publicKey, signatures } = identity
// Verify that identity was signed by the ID // Verify that identity was signed by the ID
return KeyStore.verify( return KeyStore.verify(signatures.publicKey, id, publicKey + signatures.id)
identity.signatures.publicKey,
identity.id,
identity.publicKey + identity.signatures.id
)
} }
} }

View File

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

View File

@ -71,7 +71,7 @@ describe('Identity', function () {
} catch (e) { } catch (e) {
err = e.toString() err = e.toString()
} }
assert.strictEqual(err, 'Error: Signatures is required') assert.strictEqual(err, 'Error: Signatures object is required')
}) })
it('throws and error if signature for id was not given in constructor', async () => { it('throws and error if signature for id was not given in constructor', async () => {
@ -81,7 +81,7 @@ describe('Identity', function () {
} catch (e) { } catch (e) {
err = e.toString() err = e.toString()
} }
assert.strictEqual(err, 'Error: Signature of the id is required') assert.strictEqual(err, 'Error: Signature of id is required')
}) })
it('throws and error if signature for publicKey was not given in constructor', async () => { it('throws and error if signature for publicKey was not given in constructor', async () => {
@ -91,7 +91,7 @@ describe('Identity', function () {
} catch (e) { } catch (e) {
err = e.toString() err = e.toString()
} }
assert.strictEqual(err, 'Error: Signature of (publicKey + idSignature) is required') assert.strictEqual(err, 'Error: Signature of publicKey+id is required')
}) })
it('throws and error if signature for publicKey was not given in constructor', async () => { it('throws and error if signature for publicKey was not given in constructor', async () => {
@ -101,7 +101,7 @@ describe('Identity', function () {
} catch (e) { } catch (e) {
err = e.toString() err = e.toString()
} }
assert.strictEqual(err, 'Error: Signature of the id is required') assert.strictEqual(err, 'Error: Signature of id is required')
}) })
// it('throws and error if identity provider was not given in constructor', async () => { // it('throws and error if identity provider was not given in constructor', async () => {