mirror of
https://github.com/profullstack/logicsrc.git
synced 2026-09-10 19:26:00 +00:00
Add the LogicSRC OpenSwarm specification family (#142)
BitTorrent distributes bytes better than any CDN and has never been a product: nobody is paid to seed, and nothing in it is private. Every Profullstack media property answers that with a central HTTP proxy and a pass system bolted on, and pays for every byte it serves. OpenSwarm is an add-on to BitTorrent, carried as BEP 10 extension messages, that fixes both. The swarm carries AES-256-CTR ciphertext whose integrity is pinned by two SHA-256 merkle roots in a signed manifest, so a tracker or DHT node learns an infohash and a size. A leecher buys a pass over x402 in USDC (the same exchange x402-gateway runs for crawl passes, settled by CoinPay), a seeder serves inside a bounded credit window, and the leecher signs a cumulative voucher for every verified batch. Whoever seeds gets paid. Vanilla clients remain valid members and browsers remain first-class peers. Adding a file mints a key pair for it, derived from one publisher seed by default so there is one thing to back up: the public half is the file's identity and its BEP 46 key, the private half signs the manifest and authorises grants and payout changes, and a separate content key encrypts the bytes and is sealed to paying peers. The family: a core (records, keys, hashing, transports, discovery, events), ipfile, ippay, ipdb (a signed hash-chained catalogue with heads on the DHT), ipaudio, ipvideo, iplive (paid relays with backpressure) and ipname (Moshpit pins and DNS TXT). Plus the c0mpute.com integration with seven workload types and thirteen use cases, a proposed ip CLI, conformance profiles, a security model and an FAQ. Registered on the site the way OpenCreds is: nav entry, docs registry, sitemap, a /openswarm landing page, PRD 0005, and the MCP prd_next_id expectation moved to 0006. Specs only. No code, no schemas, no reference implementation. Claude-Session: https://claude.ai/code/session_01YafYxayh7Gqe5MWNNQMev2 Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
parent
93af4770ac
commit
4fed2681ec
21 changed files with 4609 additions and 1 deletions
133
docs/openswarm/security.md
Normal file
133
docs/openswarm/security.md
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
# OpenSwarm Security Model
|
||||
|
||||
Version: **0.1** (draft)
|
||||
|
||||
This document collects the security claims the member documents make and
|
||||
states plainly what the family does not protect.
|
||||
|
||||
## 1. What is protected, by what
|
||||
|
||||
| Asset | Protection | Where |
|
||||
| --- | --- | --- |
|
||||
| File contents | AES-256-CTR under a random content key; integrity from two SHA-256 merkle trees pinned by a signed manifest | ipfile §4 |
|
||||
| Content key in transit | X25519 sealed box to the recipient's box key | ipfile §3.2 |
|
||||
| Content key at rest for the owner | Sealed to the file box key; recoverable from seed plus manifest | core §4.3 |
|
||||
| Manifest authenticity | Ed25519 by the file key and the publisher key, with a domain prefix | core §3.4 |
|
||||
| Latest-manifest pointer | BEP 44 signature by the file key, `seq` monotonic | core §7.2 |
|
||||
| Catalogue integrity | Per-entry signature plus hash chain; head on the DHT | ipdb §3 |
|
||||
| Passes | Ed25519 by the hub; payer bound by a request signature | ippay §3 |
|
||||
| Vouchers | Ed25519 by the payer; cumulative; `usd` recomputed by the payee | ippay §4 |
|
||||
| Live segments | Same cipher; root in a signed head per unit; relays verify before forwarding | iplive §3 |
|
||||
| Name to key | Registry pin (SHA-256 of SPKI) or DNS TXT, plus a signed record | ipname §4 |
|
||||
| Peer identity on a connection | `hello` signature over infohash and both peer ids | ipfile §5.1 |
|
||||
| Link confidentiality (optional) | MTP/1: X25519 + ML-KEM-768, ML-DSA-65, ChaCha20-Poly1305 | core §6.5 |
|
||||
| Events | Standard Webhooks HMAC-SHA256 with timestamp tolerance | core §8 |
|
||||
|
||||
## 2. Key material
|
||||
|
||||
| Key | Type | Lives | Backs up as |
|
||||
| --- | --- | --- | --- |
|
||||
| Publisher seed | 32 bytes | Keystore or OpenCreds `key` item | The one thing to back up |
|
||||
| File seed (derived) | HKDF from publisher seed and `fileId` | Never stored | Recomputed |
|
||||
| File seed (standalone) | 32 random bytes | Keystore | Its own OpenCreds item |
|
||||
| Content key | 32 random bytes | Keystore, `keys.owner`, keepers, grantees | `keys.owner` |
|
||||
| Box keys | X25519 from the seeds | Derived | Recomputed |
|
||||
| Hub signing key | Ed25519 | Hub HSM | Hub's problem |
|
||||
| Payer EVM key | secp256k1 | `X402_PRIVATE_KEY`, wallet | Wallet |
|
||||
| Node identity | libp2p Ed25519 | `~/.config/c0mpute/identity.key` | c0mpute's problem |
|
||||
|
||||
## 3. Threats and answers
|
||||
|
||||
**A public tracker or DHT node wants to know what a swarm is.** It gets an
|
||||
infohash, a size, a piece length, a peer count, and a file named by a hex
|
||||
string. The manifest is not on the DHT; the pointer to it is signed and
|
||||
opaque. With `swarm.private` it gets nothing from the DHT at all.
|
||||
|
||||
**A peer wants bytes without paying.** It gets one credit window per
|
||||
identity per session, then a choke. With `policy.vanilla: "ciphertext"` it
|
||||
can get all the ciphertext free, by design, and cannot read it.
|
||||
|
||||
**A seeder wants to be paid for bytes it did not serve.** It cannot; the
|
||||
voucher is signed by the payer for bytes the payer verified. Its only lever
|
||||
is to stop serving after being paid for what it already sent.
|
||||
|
||||
**A payer signs vouchers past its cap to many seeders.** Each seeder was
|
||||
exposed for one window. The hub pays in redemption order until the cap
|
||||
and refuses the rest; the payer's standing records it and future passes
|
||||
are refused.
|
||||
|
||||
**A payer or seeder replays a voucher.** It is cumulative and per triple;
|
||||
replay pays zero.
|
||||
|
||||
**A hub key is stolen.** Free passes until manifests drop the hub. The hub
|
||||
record SHOULD carry a successor key and publishers SHOULD list two hubs.
|
||||
|
||||
**A hub does not pay out.** It is a trusted processor; the answer is to
|
||||
list a different hub. Receipts are signed, so non-payment is provable.
|
||||
|
||||
**The publisher seed is stolen.** Every derived file key is compromised:
|
||||
the thief can revise manifests, change payout addresses and delegate
|
||||
keepers. Detection is a manifest revision the owner did not make, visible
|
||||
in the `ipdb` log. Remedy is publisher rotation (core §4.5) from a machine
|
||||
the thief does not control; `successor` links require the new key too, so
|
||||
the thief cannot forge the rotation.
|
||||
|
||||
**The publisher seed is lost.** Core §4.7. Nothing is unreadable; nothing
|
||||
can be changed.
|
||||
|
||||
**A grantee leaks the content key.** Anyone with the key and the ciphertext
|
||||
reads the file. The family prices access and does not prevent copying. A
|
||||
leaked key is answered by re-encryption, which protects only future
|
||||
readers. This is the same position every streaming service is in once the
|
||||
frame is on a screen, stated rather than hidden behind a DRM promise.
|
||||
|
||||
**A relay forwards a bad segment.** Every downstream peer verifies the root
|
||||
against a signed head and drops the relay.
|
||||
|
||||
**A Sybil of relays surrounds an origin.** They pull, earn nothing (nobody
|
||||
pays them), and cost the origin upload up to `maxDownstream`. Pins and
|
||||
hired relays are how an origin buys reach it controls.
|
||||
|
||||
**A registry hands out a wrong pin.** The record fails the pin check;
|
||||
first-seen pinning in the resolver warns on change.
|
||||
|
||||
**An EIP-3009 proof is presented for a different resource.** Known
|
||||
limitation of x402 v2: the struct cannot bind a resource. The hub records
|
||||
nonce to resource at verify time and refuses reuse (ippay §3.2).
|
||||
|
||||
**A gateway is asked to serve plaintext to a bare `<video>` tag.** It serves
|
||||
one credit window against the pass and then 402s; a gateway configured to
|
||||
trust the pass for the whole title is taking the whole title as its
|
||||
exposure, and the configuration says so.
|
||||
|
||||
## 4. What is deliberately visible
|
||||
|
||||
- File size, piece length, both infohashes, tracker list, peer count.
|
||||
- Manifest `name` and `meta`, to anyone who obtains the manifest (public
|
||||
visibility) or any pass holder (pass visibility).
|
||||
- The existence and sequence length of a feed; the content of a public
|
||||
feed.
|
||||
- Segment sizes and timing of a live stream, to relays.
|
||||
- Who paid whom how much, to the hub.
|
||||
- The publisher's payout address, in the signed manifest.
|
||||
|
||||
## 5. Defaults an implementation MUST ship
|
||||
|
||||
| Setting | Default | Reason |
|
||||
| --- | --- | --- |
|
||||
| `policy.creditBytes` | 4 MiB (`ipfile`), 8 MiB (`iplive`) | Bounded exposure, no choke at the live edge |
|
||||
| `policy.voucherBytes` | 1 MiB, 2 MiB | Four vouchers per window |
|
||||
| `policy.vanilla` | `ciphertext` | Wider swarm at zero confidentiality cost |
|
||||
| `visibility` | `public` | A catalogue that cannot be read is not a catalogue |
|
||||
| Pass lifetime | 30 days | Long enough to stream a release, short enough to bound a stolen key |
|
||||
| Key epoch (`iplive`) | 900 segments | 30 minutes at 2 s |
|
||||
| Resolver cache | 300 s positive, 5 s negative | Matches moshpit-proxy |
|
||||
| Keystore mode | 0600 | As every other Profullstack keystore |
|
||||
|
||||
## 6. Cryptographic agility
|
||||
|
||||
`cipher.alg`, `sigs[].alg`, `kdf` labels with `:v1` suffixes, and
|
||||
extension names are all versioned data. A new cipher is a new `alg` value
|
||||
and a new IV label; a new signature is a new `alg`; a breaking wire change
|
||||
is a new extension name. Nothing is edited in place, for the reason
|
||||
OpenCreds gives: peers that shipped the old value are still running.
|
||||
Loading…
Add table
Add a link
Reference in a new issue