49 lines
1.7 KiB
JavaScript
49 lines
1.7 KiB
JavaScript
import b4a from 'b4a'
|
|
import crypto from 'hypercore-crypto'
|
|
|
|
export const PROTOCOL_NAME = 'bare-os-v1'
|
|
export const TOPIC_STRING = 'bare-os-v1'
|
|
/** Optional second Protomux channel for app-level RPC (paired when `BARE_OS_PROTOMUX_APP_CHANNEL` is set). */
|
|
export const PROTOCOL_APP_CHANNEL_NAME = 'bare-os-app-v1'
|
|
/** Optional capability/datagram side channel (paired when `BARE_OS_PROTOMUX_CAP_CHANNEL` is set). */
|
|
export const PROTOCOL_CAP_CHANNEL_NAME = 'bare-os-cap-v1'
|
|
/** Global swarm chat channel (paired by default; opt out with `BARE_OS_PROTOMUX_CHAT_CHANNEL=0`). */
|
|
export const PROTOCOL_CHAT_CHANNEL_NAME = 'bare-os-chat-v1'
|
|
/** Meshdrop control/data channel (paired by default; opt out with `BARE_OS_PROTOMUX_MESHDROP_CHANNEL=0`). */
|
|
export const PROTOCOL_MESHDROP_CHANNEL_NAME = 'bare-os-meshdrop-v1'
|
|
export const BLOCK_SIZE = 512
|
|
export const MBR_MAGIC = b4a.from('BIOS')
|
|
|
|
export function topicKey(b4aMod = b4a) {
|
|
return crypto.hash(b4aMod.from(TOPIC_STRING))
|
|
}
|
|
|
|
export function buildMbr(primaryKey, failoverKeys = []) {
|
|
if (primaryKey.byteLength !== 32) {
|
|
throw new Error('primaryKey must be 32 bytes')
|
|
}
|
|
const mbr = b4a.alloc(BLOCK_SIZE)
|
|
mbr.set(MBR_MAGIC)
|
|
mbr.set(primaryKey, 8)
|
|
const slots = [40, 72]
|
|
for (let i = 0; i < slots.length; i++) {
|
|
const k = failoverKeys[i]
|
|
if (k) {
|
|
if (k.byteLength !== 32) throw new Error('failover key must be 32 bytes')
|
|
mbr.set(k, slots[i])
|
|
}
|
|
}
|
|
return mbr
|
|
}
|
|
|
|
export function parseMbr(mbr) {
|
|
if (mbr.byteLength < 104) throw new Error('MBR too short')
|
|
if (b4a.toString(mbr.slice(0, 4)) !== 'BIOS') {
|
|
throw new Error('Invalid MBR magic')
|
|
}
|
|
const keys = [mbr.slice(8, 40), mbr.slice(40, 72), mbr.slice(72, 104)].filter(
|
|
(k) => !b4a.equals(k, b4a.alloc(32))
|
|
)
|
|
return { keys }
|
|
}
|