Updates
This commit is contained in:
@@ -1,34 +1,92 @@
|
||||
# hyper-p2p-encrypted-topic
|
||||
|
||||
Production module: Topic encryption demo.
|
||||
Register topics with a `keyHint`, derive a symmetric key, XOR-encrypt payloads; gossip topic registration (hint only).
|
||||
|
||||
**Protocol:** `encrypted-topic/v1`
|
||||
**Category:** trust-security · **Protocol:** `encrypted-topic/v1` · **Exports:** `HyperP2PEncryptedTopic`, `PROTOCOL`, `deriveKey`, `xorCrypt`
|
||||
|
||||
## When to use
|
||||
|
||||
Topic-scoped payload crypto.
|
||||
Lightweight obfuscation keyed by shared hint on a mesh (not a substitute for Noise).
|
||||
|
||||
## When not to use
|
||||
|
||||
Production AEAD.
|
||||
Production confidentiality without real AEAD/Noise.
|
||||
|
||||
## Quick start
|
||||
|
||||
```js
|
||||
const { HyperP2PEncryptedTopic } = require('hyper-p2p-encrypted-topic')
|
||||
const m = new HyperP2PEncryptedTopic()
|
||||
m.registerTopic('t','hint')
|
||||
await m.ready()
|
||||
await m.close()
|
||||
const enc = new HyperP2PEncryptedTopic({ topic: 'secure' })
|
||||
await enc.ready()
|
||||
enc.registerTopic('private-feed', 'shared-secret-hint')
|
||||
const cipher = enc.encryptPayload('private-feed', 'hello')
|
||||
console.log(enc.decryptPayload('private-feed', cipher).toString())
|
||||
await enc.close()
|
||||
```
|
||||
|
||||
## Docs
|
||||
|
||||
- [docs/api.md](docs/api.md)
|
||||
- [docs/architecture.md](docs/architecture.md)
|
||||
- [docs/api.md](docs/api.md) · [docs/architecture.md](docs/architecture.md)
|
||||
|
||||
## Test
|
||||
|
||||
```bash
|
||||
npm install && npm test
|
||||
npm test
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
| Member | Description |
|
||||
|--------|-------------|
|
||||
| `new HyperP2PEncryptedTopic(opts?)` | `topic`, `keyPair`. |
|
||||
| `registerTopic(topicId, keyHint)` | `key = hash(keyHint)`; gossips `topic-register`. |
|
||||
| `encryptPayload(topicId, data)` | Buffer or encodable; returns cipher buffer. |
|
||||
| `decryptPayload(topicId, buf)` | XOR decrypt; requires registered topic. |
|
||||
| `deriveKey(hint)` / `xorCrypt(keyBuf, dataBuf)` | Low-level helpers (exported). |
|
||||
| `getStats()` | `{ registered, encrypted, decrypted, gossipIn, gossipOut, topics, protocol }`. |
|
||||
| `ready()` / `close()` | Swarm lifecycle. |
|
||||
|
||||
**Events:** `registered`, `closed`. Remote register fills map if `topicId` new.
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
_topics Map(topicId -> { keyHint, key, registeredAt })
|
||||
deriveKey: hypercore-crypto.hash(b4a.from(String(hint)))
|
||||
xorCrypt: repeating-key XOR byte-wise
|
||||
```
|
||||
|
||||
Peers must use same `keyHint` for a `topicId` to decrypt. Gossip shares hint, not key bytes.
|
||||
|
||||
## Wire table
|
||||
|
||||
| `type` | Fields | Direction |
|
||||
|--------|--------|-----------|
|
||||
| `topic-register` | `topicId`, `keyHint` | Any → all |
|
||||
|
||||
## Errors
|
||||
|
||||
- Unregistered `topicId` on encrypt/decrypt throws `topic not registered`.
|
||||
- `decryptPayload`: non-buffer input throws.
|
||||
- Empty `topicId` / `keyHint` on register.
|
||||
|
||||
## Composition
|
||||
|
||||
- XOR is not AEAD—layer Noise or app crypto for real secrecy.
|
||||
- Same `keyHint` across peers required; rotate via `hyper-p2p-key-rotation` on hint strings.
|
||||
- Gossip does not re-broadcast ciphertext—only registration.
|
||||
|
||||
## Example
|
||||
|
||||
```js
|
||||
const { HyperP2PEncryptedTopic } = require('hyper-p2p-encrypted-topic')
|
||||
|
||||
const enc = new HyperP2PEncryptedTopic({ topic: process.argv[2] })
|
||||
await enc.ready()
|
||||
|
||||
enc.registerTopic('private-feed', 'shared-secret-hint')
|
||||
const cipher = enc.encryptPayload('private-feed', 'hello')
|
||||
const plain = enc.decryptPayload('private-feed', cipher)
|
||||
console.log(plain.toString())
|
||||
await enc.close()
|
||||
```
|
||||
|
||||
@@ -1,26 +1,91 @@
|
||||
# API: hyper-p2p-encrypted-topic
|
||||
|
||||
**Protocol:** `encrypted-topic/v1` · **Export:** `HyperP2PEncryptedTopic`
|
||||
**Protocol:** `encrypted-topic/v1` · **Export:** `HyperP2PEncryptedTopic`, `PROTOCOL`, `deriveKey`, `xorCrypt`
|
||||
|
||||
## Overview
|
||||
|
||||
Registers logical topics with a `keyHint`, derives a symmetric key via `hypercore-crypto.hash`, and XOR-encrypts payloads. Gossips `topic-register` so peers learn hints (not raw keys — key re-derived locally).
|
||||
|
||||
## Constructor
|
||||
|
||||
| Option | Type | Default | Description |
|
||||
|--------|------|---------|-------------|
|
||||
| `topic` | `string` \| `Buffer` | `null` | Swarm topic |
|
||||
| `keyPair` | `KeyPair` | random | Swarm identity |
|
||||
|
||||
## Methods
|
||||
|
||||
### `registerTopic(...)`
|
||||
### `registerTopic(topicId, keyHint)`
|
||||
|
||||
Domain API.
|
||||
- **Returns:** `{ topicId, keyHint, key, registeredAt }`
|
||||
- **Throws:** `assertNonEmpty` on both args
|
||||
- **Gossip:** `{ type: 'topic-register', topicId, keyHint }`
|
||||
- **Emits:** `registered` `{ topicId, keyHint }`
|
||||
|
||||
### `encryptPayload(...)`
|
||||
### `encryptPayload(topicId, data)`
|
||||
|
||||
Domain API.
|
||||
- **Returns:** Buffer cipher
|
||||
- **Throws:** `topic not registered: ${topicId}`
|
||||
|
||||
### `decryptPayload(...)`
|
||||
### `decryptPayload(topicId, buf)`
|
||||
|
||||
Domain API.
|
||||
- **Returns:** plain Buffer
|
||||
- **Throws:** `buf must be a buffer`; `topic not registered: ${topicId}`
|
||||
|
||||
### `ready()` / `close()`
|
||||
|
||||
### `getStats()` / `ready()` / `close()`
|
||||
Standard swarm.
|
||||
|
||||
Lifecycle helpers.
|
||||
## Events
|
||||
|
||||
| Event | Payload |
|
||||
|-------|---------|
|
||||
| `registered` | `{ topicId, keyHint }` |
|
||||
| `closed` | — |
|
||||
|
||||
## getStats()
|
||||
|
||||
`registered`, `encrypted`, `decrypted`, `gossipIn`, `gossipOut`, `topics`, `protocol`.
|
||||
|
||||
## Wire
|
||||
|
||||
| type | fields | behavior |
|
||||
|------|--------|----------|
|
||||
| `topic-register` | `topicId`, `keyHint` | Insert topic if unknown; derive key |
|
||||
|
||||
## Errors
|
||||
|
||||
Registration and buffer errors above. Uses `assertNonEmpty` from shared errors.
|
||||
|
||||
See [`../../_shared/ERROR_CODES.md`](../../_shared/ERROR_CODES.md).
|
||||
|
||||
## P2P
|
||||
|
||||
Joins Hyperswarm when `topic` is set.
|
||||
XOR is not authenticated encryption — use for obfuscation/lightweight topic privacy only.
|
||||
|
||||
## Testing
|
||||
|
||||
```bash
|
||||
cd modules/trust-security/hyper-p2p-encrypted-topic && npm test
|
||||
```
|
||||
|
||||
## Composition
|
||||
|
||||
`hyper-p2p-topic-announcer`, `hyper-p2p-key-rotation`, `hyper-p2p-session-rotation`.
|
||||
|
||||
## Example
|
||||
|
||||
See [`examples/basic.js`](../examples/basic.js).
|
||||
|
||||
## Remote merge rules
|
||||
|
||||
- `topic-register` only inserts when `topicId` not already local
|
||||
- Remote peers re-derive `key` from gossiped `keyHint` (never send raw key)
|
||||
|
||||
## Lifecycle
|
||||
|
||||
Encrypt/decrypt increment `encrypted` / `decrypted` stats per operation.
|
||||
|
||||
## See also
|
||||
|
||||
[`docs/architecture.md`](architecture.md), [`../../MODULE_CATEGORIES.md`](../../MODULE_CATEGORIES.md).
|
||||
|
||||
@@ -1,11 +1,22 @@
|
||||
# Architecture: hyper-p2p-encrypted-topic
|
||||
|
||||
**Protocol:** `encrypted-topic/v1` · **Category:** trust-security
|
||||
|
||||
## Wire messages
|
||||
|
||||
| type | fields | direction | behavior |
|
||||
|------|--------|-----------|----------|
|
||||
| `topic-register` | topicId, keyHint | gossip | Register |
|
||||
| type | direction | fields | behavior |
|
||||
|------|-----------|--------|----------|
|
||||
| `topic-register` | gossip | `topicId`, `keyHint` | Store topic; `deriveKey(keyHint)` locally |
|
||||
|
||||
## State
|
||||
## State model
|
||||
|
||||
In-memory structures; gossip via `initModuleSwarm` / `gossipSend` when P2P enabled.
|
||||
`_topics`: Map topicId → `{ topicId, keyHint, key, registeredAt }`.
|
||||
|
||||
## Helpers
|
||||
|
||||
- `deriveKey(hint)` → `crypto.hash(b4a.from(String(hint)))`
|
||||
- `xorCrypt(keyBuf, dataBuf)` — byte XOR stream cipher
|
||||
|
||||
## Composition
|
||||
|
||||
`hyper-p2p-key-rotation`, `hyper-p2p-topic-announcer`.
|
||||
|
||||
Reference in New Issue
Block a user