mirror of
https://github.com/orbitdb/orbitdb.git
synced 2025-07-07 13:02:29 +00:00
feat: Encrypt oplog payload.
This commit is contained in:
parent
90f66cfe5d
commit
f272d3ee3c
@ -7,7 +7,6 @@
|
|||||||
* @augments module:Databases~Database
|
* @augments module:Databases~Database
|
||||||
*/
|
*/
|
||||||
import Database from '../database.js'
|
import Database from '../database.js'
|
||||||
import { toPayload, fromPayload } from './utils/payload.js'
|
|
||||||
|
|
||||||
const type = 'events'
|
const type = 'events'
|
||||||
|
|
||||||
@ -16,7 +15,7 @@ const type = 'events'
|
|||||||
* @return {module:Databases.Databases-Events} A Events function.
|
* @return {module:Databases.Databases-Events} A Events function.
|
||||||
* @memberof module:Databases
|
* @memberof module:Databases
|
||||||
*/
|
*/
|
||||||
const Events = () => async ({ ipfs, identity, address, name, access, directory, meta, headsStorage, entryStorage, indexStorage, referencesCount, syncAutomatically, onUpdate, encrypt }) => {
|
const Events = () => async ({ ipfs, identity, address, name, access, directory, meta, headsStorage, entryStorage, indexStorage, referencesCount, syncAutomatically, onUpdate }) => {
|
||||||
const database = await Database({ ipfs, identity, address, name, access, directory, meta, headsStorage, entryStorage, indexStorage, referencesCount, syncAutomatically, onUpdate })
|
const database = await Database({ ipfs, identity, address, name, access, directory, meta, headsStorage, entryStorage, indexStorage, referencesCount, syncAutomatically, onUpdate })
|
||||||
|
|
||||||
const { addOperation, log } = database
|
const { addOperation, log } = database
|
||||||
@ -30,8 +29,7 @@ const Events = () => async ({ ipfs, identity, address, name, access, directory,
|
|||||||
* @instance
|
* @instance
|
||||||
*/
|
*/
|
||||||
const add = async (value) => {
|
const add = async (value) => {
|
||||||
const payload = await toPayload('ADD', null, value, { encrypt })
|
return addOperation({ op: 'ADD', key: null, value })
|
||||||
return addOperation(payload)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -44,9 +42,7 @@ const Events = () => async ({ ipfs, identity, address, name, access, directory,
|
|||||||
*/
|
*/
|
||||||
const get = async (hash) => {
|
const get = async (hash) => {
|
||||||
const entry = await log.get(hash)
|
const entry = await log.get(hash)
|
||||||
const { value } = await fromPayload(entry.payload, { encrypt })
|
return entry.payload.value
|
||||||
|
|
||||||
return value
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -70,8 +66,7 @@ const Events = () => async ({ ipfs, identity, address, name, access, directory,
|
|||||||
const it = log.iterator({ gt, gte, lt, lte, amount })
|
const it = log.iterator({ gt, gte, lt, lte, amount })
|
||||||
for await (const event of it) {
|
for await (const event of it) {
|
||||||
const hash = event.hash
|
const hash = event.hash
|
||||||
const payload = await fromPayload(event.payload, { encrypt })
|
const value = event.payload.value
|
||||||
const value = payload.value
|
|
||||||
yield { hash, value }
|
yield { hash, value }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,39 +0,0 @@
|
|||||||
/**
|
|
||||||
|
|
||||||
*/
|
|
||||||
const toPayload = async (op, key, value, { encrypt }) => {
|
|
||||||
let payload = { op, key, value }
|
|
||||||
|
|
||||||
if (encrypt) {
|
|
||||||
if (encrypt.data) {
|
|
||||||
payload.value = await encrypt.data.encryptFn(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (encrypt.op) {
|
|
||||||
payload = await encrypt.op.encryptFn(JSON.stringify(payload))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return payload
|
|
||||||
}
|
|
||||||
|
|
||||||
const fromPayload = async (payload, { encrypt }) => {
|
|
||||||
if (encrypt) {
|
|
||||||
if (encrypt.op) {
|
|
||||||
payload = JSON.parse(await encrypt.op.decryptFn(payload))
|
|
||||||
}
|
|
||||||
|
|
||||||
if (encrypt.data) {
|
|
||||||
payload.value = await encrypt.data.decryptFn(payload.value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const { op, key, value } = payload
|
|
||||||
|
|
||||||
return { op, key, value }
|
|
||||||
}
|
|
||||||
|
|
||||||
export {
|
|
||||||
toPayload,
|
|
||||||
fromPayload
|
|
||||||
}
|
|
@ -56,7 +56,7 @@ const DefaultAccessController = async () => {
|
|||||||
* @memberof module:Log
|
* @memberof module:Log
|
||||||
* @instance
|
* @instance
|
||||||
*/
|
*/
|
||||||
const Log = async (identity, { logId, logHeads, access, entryStorage, headsStorage, indexStorage, sortFn } = {}) => {
|
const Log = async (identity, { logId, logHeads, access, entryStorage, headsStorage, indexStorage, sortFn, encryption } = {}) => {
|
||||||
/**
|
/**
|
||||||
* @namespace Log
|
* @namespace Log
|
||||||
* @description The instance returned by {@link module:Log}
|
* @description The instance returned by {@link module:Log}
|
||||||
@ -83,6 +83,9 @@ const Log = async (identity, { logId, logHeads, access, entryStorage, headsStora
|
|||||||
// Conflict-resolution sorting function
|
// Conflict-resolution sorting function
|
||||||
sortFn = NoZeroes(sortFn || LastWriteWins)
|
sortFn = NoZeroes(sortFn || LastWriteWins)
|
||||||
|
|
||||||
|
encryption = encryption || {}
|
||||||
|
const { encryptPayloadFn, decryptPayloadFn } = encryption
|
||||||
|
|
||||||
// Internal queues for processing appends and joins in their call-order
|
// Internal queues for processing appends and joins in their call-order
|
||||||
const appendQueue = new PQueue({ concurrency: 1 })
|
const appendQueue = new PQueue({ concurrency: 1 })
|
||||||
const joinQueue = new PQueue({ concurrency: 1 })
|
const joinQueue = new PQueue({ concurrency: 1 })
|
||||||
@ -139,6 +142,10 @@ const Log = async (identity, { logId, logHeads, access, entryStorage, headsStora
|
|||||||
if (bytes) {
|
if (bytes) {
|
||||||
const entry = await Entry.decode(bytes)
|
const entry = await Entry.decode(bytes)
|
||||||
|
|
||||||
|
if (decryptPayloadFn) {
|
||||||
|
entry.payload = JSON.parse(await decryptPayloadFn(entry.payload))
|
||||||
|
}
|
||||||
|
|
||||||
return entry
|
return entry
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -172,6 +179,10 @@ const Log = async (identity, { logId, logHeads, access, entryStorage, headsStora
|
|||||||
// (skips the heads which are covered by the next field)
|
// (skips the heads which are covered by the next field)
|
||||||
const refs = await getReferences(heads_, options.referencesCount + heads_.length)
|
const refs = await getReferences(heads_, options.referencesCount + heads_.length)
|
||||||
|
|
||||||
|
if (encryptPayloadFn) {
|
||||||
|
data = await encryptPayloadFn(JSON.stringify(data))
|
||||||
|
}
|
||||||
|
|
||||||
// Create the entry
|
// Create the entry
|
||||||
const entry = await Entry.create(
|
const entry = await Entry.create(
|
||||||
identity,
|
identity,
|
||||||
|
@ -3,6 +3,7 @@ import { rimraf } from 'rimraf'
|
|||||||
import { copy } from 'fs-extra'
|
import { copy } from 'fs-extra'
|
||||||
import { Log, Entry, Identities, KeyStore, MemoryStorage } from '../../src/index.js'
|
import { Log, Entry, Identities, KeyStore, MemoryStorage } from '../../src/index.js'
|
||||||
import testKeysPath from '../fixtures/test-keys-path.js'
|
import testKeysPath from '../fixtures/test-keys-path.js'
|
||||||
|
import { encrypt, decrypt } from '../utils/encrypt.js'
|
||||||
|
|
||||||
const { create } = Entry
|
const { create } = Entry
|
||||||
|
|
||||||
@ -142,5 +143,34 @@ describe('Log', function () {
|
|||||||
strictEqual(values[1].payload, 'hello2')
|
strictEqual(values[1].payload, 'hello2')
|
||||||
strictEqual(values[2].payload, 'hello3')
|
strictEqual(values[2].payload, 'hello3')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('encrypts a log entry when the payload is a string', async () => {
|
||||||
|
const keys = await keystore.createKey('hello1')
|
||||||
|
|
||||||
|
const privateKey = await keystore.getKey('hello1')
|
||||||
|
const publicKey = await keystore.getPublic(keys)
|
||||||
|
|
||||||
|
const encryptPayloadFn = encrypt({ publicKey })
|
||||||
|
const decryptPayloadFn = decrypt({ privateKey })
|
||||||
|
const log = await Log(testIdentity, { encryption: { encryptPayloadFn, decryptPayloadFn } })
|
||||||
|
const entry = await log.append('hello1')
|
||||||
|
const value = await log.get(entry.hash)
|
||||||
|
strictEqual(value.payload, 'hello1')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('encrypts a log entry when the payload is an object', async () => {
|
||||||
|
const keys = await keystore.createKey('hello1')
|
||||||
|
|
||||||
|
const privateKey = await keystore.getKey('hello1')
|
||||||
|
const publicKey = await keystore.getPublic(keys)
|
||||||
|
|
||||||
|
const encryptPayloadFn = encrypt({ publicKey })
|
||||||
|
const decryptPayloadFn = decrypt({ privateKey })
|
||||||
|
const log = await Log(testIdentity, { encryption: { encryptPayloadFn, decryptPayloadFn } })
|
||||||
|
const entry = await log.append({ test: 'hello1' })
|
||||||
|
const value = await log.get(entry.hash)
|
||||||
|
|
||||||
|
deepStrictEqual(value.payload, { test: 'hello1' })
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
Loading…
x
Reference in New Issue
Block a user