Manyleb Protocol qub
Mae qub yn brotocol ar gyfer ymrwymiadau amserol cryptograffig: system ar gyfer selio geiriau i ddyddiad yn y dyfodol a phrofi, pan fydd y dyddiad hwnnw'n cyrraedd, yn union beth a ddywedwyd a phryd.
Mae tri phrimitif yn gwneud i hyn weithio. Mae drand yn oleudy hap datganoledig — mae'r dyddiad datgelu yn orfodadwy gan ffiseg, nid gan ewyllys da unrhyw barti. Mae storfa gyhoeddus barhaol yn storfa gyhoeddus gwrth-ymyrryd — ni all unrhyw barti olygu na dileu qub unwaith y mae wedi'i selio. Mae ML-DSA-65 yn lofnod digidol ôl-gwantwm — mae pob qub wedi'i glymu wrth bâr o allweddi nad yw eu cyfrinach byth yn gadael dyfais yr awdur.
Gyda'i gilydd, mae'r primitifau hyn yn gwneud datganiad sydd wedi'i gloi-amser, yn dystiolaeth o ymyrraeth, ac yn briodoladwy — derbynneb y mae ei gwerth yn tyfu wrth i allu'r byd i ffugio'r gorffennol wella.
Mae gweddill y ddogfen hon yn fanyleb normadol sy'n ofynnol ar gyfer gweithrediadau rhyngweithredadwy.
Manyleb Protocol qub
| Maes | Gwerth |
|---|---|
| Fersiwn | 1.0 (fersiwn protocol 0x01, fersiwn amlapio allanol 0x01) |
| Dyddiad | 2026-05-01 |
| Statws | Drafft |
| Adolygwyd hyd at | 2026-05-01 |
Y ddogfen hon yw'r fanyleb protocol normadol ar gyfer system ymrwymiad amserol qub. Mae'n diffinio strwythurau data, rheolau cyfresoli, fformiwlâu deilliad, a gweithdrefnau dilysu sy'n ofynnol ar gyfer gweithrediadau rhyngweithredadwy.
Cwmpas: mae haen y protocol yn fwriadol-niwtral o ran iaith — bytes plaen / markdown / cytundeb yw corff y qub yn ddi-ddehongli, ac mae rendro ymwybodol-o-leoliad yn gyfrifoldeb y gwyliwr (ap gwe qub.social, iframe <qub-embed>, cleientiaid MCP, ac ati).
1. Nodiant a Chonfensiynau
| Nodiant | Ystyr |
|---|---|
u8, u64, i64 |
Cyfanrifau anarwyddedig/arwyddedig o led bit penodol |
[u8; N] |
Arae byte o hyd sefydlog N bytes |
Vec<u8> |
Arae byte o hyd amrywiol |
Option<T> |
Gwerth o fath T, neu absennol |
String |
Llinyn testun UTF-8, wedi'i normaleiddio NFC |
| ` | |
SHA3-256(x) |
Hash NIST SHA3-256 o linyn byte x (FIPS 202) |
ceil(x) |
Swyddogaeth nenfwd: cyfanrif lleiaf ≥ x |
| CBOR | Concise Binary Object Representation (RFC 8949) |
| big-endian | Y byte mwyaf arwyddocaol yn gyntaf |
Mae pob cyfanrif mewn strwythurau preimage wedi'u hamgodio fel araeau byte big-endian o led sefydlog (i64 → 8 byte, u8 → 1 byte) oni nodir fel arall.
Mae pob amserlin yn eiliadau Unix yn UTC.
2. Strwythurau Data
2.1 ComposeQub (Cyflwr Yn-Cof y Crëwr)
Heb ei gyfresoli i CBOR. Heb ei ysgrifennu i storfa parhaol. Lleol i ap y crëwr.
ComposeQub {
draft_id: [u8; 16], // Random, generated locally
created_at: i64, // Unix seconds UTC
unlock_at: Option<i64>, // Unix seconds UTC; None while composing
visibility: u8, // 0x01 = public (only value in MVP)
content_type: u8, // 0x01 = text (only value in MVP)
plaintext: Vec<u8>, // UTF-8 qub body
sender_label: Option<String>, // Decorative display name; not authenticated
status: DraftStatus, // Composing | Sealed | Uploaded | Failed
}
2.2 QubEnvelope (Llwyth Tâl wedi'i Ddatgryptio)
Wedi'i gyfresoli gan ddefnyddio CBOR safonol (§3). Wedi'i amgryptio y tu mewn i'r SealedQub. Dyma'r strwythur sy'n profi cywirdeb cynnwys ar ôl datgryptio.
QubEnvelope {
version: u8, // Protocol major version (0x01 for v1)
qub_id: [u8; 32], // Derived (see §4.1)
content_type: u8, // Content type registry (see §6)
created_at: i64, // Unix seconds UTC
unlock_at: i64, // Unix seconds UTC
outcome_at: Option<i64>, // V1.1 — pan fydd realiti'n cynnig dyfarniad (verdict-uplift-plan §3.1)
sender_label: Option<String>, // Decorative; not authenticated in MVP
reply_to: Option<[u8; 32]>,// Parent qub_id for reply chains; not in qub_id preimage; not signed (see §9.3)
body: Vec<u8>, // Content payload (UTF-8 for text, CBOR for pact)
body_hash: [u8; 32], // SHA3-256(body) (see §4.2)
sig_alg: u8, // Signature algorithm (see §9.2)
author_signature: Option<Vec<u8>>, // Set when sig_alg != 0x00
author_pubkey: Option<Vec<u8>>, // Set when sig_alg != 0x00
cosigner_pubkey: Option<Vec<u8>>, // Set for cosigned pact bilateral agreements
cosigner_signature: Option<Vec<u8>>, // Set for cosigned pact bilateral agreements
}
Sylfaen (qub testun heb ei lofnodi): version = 0x01, content_type = 0x01, sig_alg = 0x00, pob maes Option yn absennol.
Cyfluniadau v1 eraill: content_type = 0x03 (corff cytundeb, gweler §6.1); sig_alg = 0x01 (ML-DSA-65) gydag author_signature ac author_pubkey yn bresennol (gweler §9.3); cosigner_pubkey a cosigner_signature yn bresennol gyda'i gilydd ar gyfer cytundebau wedi'u cyd-arwyddo (gweler §9.7); reply_to wedi'i osod i qub_id y qub rhiant ar gyfer qubs cadwyn-ateb (gweler §9.3 am oblygiadau cwmpas y llofnod).
2.3 SealedQub (Fformat Gwifren Safonol)
Wedi'i gyfresoli gan ddefnyddio CBOR safonol (§3). Wedi'i ysgrifennu i storfa parhaol. Dyma'r arteffact ar-y-gadwyn.
SealedQub {
version: u8, // Protocol major version (0x01 for v1)
qub_id: [u8; 32], // Same as QubEnvelope.qub_id
visibility: u8, // 0x01 = public; v1 viewers reject other values
unlock_at: i64, // Unix seconds UTC
outcome_at: Option<i64>, // V1.1 — yn ymddangos ar y CTA gwylio-dyfarniad
// cyn datgelu; yn adlewyrchu QubEnvelope.outcome_at;
// wedi'i rwymo i qub_id trwy preimage §4.1.
drand_chain_id: String, // drand chain hash (hex string)
drand_round: u64, // Target drand round number
tlock_ciphertext: Vec<u8>, // tlock-encrypted QubEnvelope CBOR bytes
recipient_pubkey: Option<[u8; 32]>,// Reserved field; accepted by canonical CBOR
// but not interpreted by the v1 reference viewer
title: Option<String>, // Plaintext title surfaced on the viewer
// countdown before reveal. Bound to qub_id
// via title_hash (§4.1). 1..=100 NFC code
// points, no control characters.
}
2.4 RevealedQub (Cyflwr Cymhwysiad y Gwyliwr)
Heb ei gyfresoli i CBOR. Lleol i ap y gwyliwr. Adeiladwyd ar ôl datgryptio a dilysu llwyddiannus.
RevealedQub {
qub_id: [u8; 32],
arweave_tx_id: String,
visibility: u8,
content_type: u8,
created_at: i64,
unlock_at: i64,
outcome_at: Option<i64>, // V1.1 — wedi'i gario ymlaen o QubEnvelope.outcome_at / SealedQub.outcome_at; yn gyrru bloc gwylio-dyfarniad tudalen y datgeliad (verdict-uplift-plan §5.1)
drand_chain_id: String,
drand_round: u64,
sender_label: Option<String>,
title: Option<String>, // Carried forward from SealedQub.title
reply_to: Option<[u8; 32]>,
body: Vec<u8>,
body_hash: [u8; 32],
body_hash_verified: bool,
author_signature: Option<Vec<u8>>,
author_pubkey: Option<Vec<u8>>,
signature_verified: Option<bool>,
cosigner_pubkey: Option<Vec<u8>>,
cosigner_signature: Option<Vec<u8>>,
cosigner_verified: Option<bool>,
}
3. Proffil CBOR Safonol
RHAID i bob cyfresoli SealedQub a QubEnvelope gydymffurfio â'r proffil hwn. RHAID i ddau weithrediad sy'n derbyn yr un strwythur rhesymegol gynhyrchu bytes union yr un fath.
3.1 Rheolau Amgodio
| Rheol | Manyleb |
|---|---|
| Safon | RFC 8949 §4.2.1 (Core Deterministic Encoding Requirements) |
| Trefnu allweddi map | Wedi'i drefnu yn ôl hyd byte wedi'i amgodio yn gyntaf (byrrach cyn hwy), yna'n lecsicograffig (byte-wrth-byte ar gyfer amgodiadau o'r un hyd) |
| Amgodio cyfanrifau | Y ffurf fyrraf: 0–23 yn y byte cychwynnol; 24–255 mewn 2 byte; 256–65535 mewn 3 byte; ac ati. |
| Amgodio hyd | Hyd pendant yn unig. Dim araeau, mapiau, llinynnau byte, na llinynnau testun o hyd amhendant (gwybodaeth ychwanegol = 31 wedi'i gwahardd). |
| Tagiau | Dim tagiau CBOR (math mawr 6 wedi'i wahardd). |
| Pwynt-arnofiol | Dim arnofiolion (gwerthoedd math mawr 7 0xF9–0xFB wedi'u gwahardd). |
| Llinynnau testun | UTF-8 wedi'i amgodio, wedi'i normaleiddio NFC (Ffurflen Normaleiddio Unicode C). |
| Llinynnau byte | Bytes amrwd. Dim amgodio base64 yn yr haen CBOR. |
| Allweddi dyblyg | Gwrthod gyda gwall. RHAID i barseyddion BEIDIO â derbyn allweddi map dyblyg yn dawel. |
| Gwerthoedd syml | Dim ond true (0xF5), false (0xF4), a null (0xF6) a ganiateir. |
| Meysydd dewisol | Mae meysydd dewisol absennol yn cael eu hepgor yn llwyr o'r map CBOR (heb eu hamgodio fel null). Mae meysydd dewisol presennol yn cael eu cynnwys yn nhrefn allweddi wedi'i didoli. |
3.2 Trefn Allweddi Safonol wedi'u Dilysu
Mae'r trefnau allweddi hyn yn normadol. RHAID i weithrediadau allyrru allweddi yn union y drefn hon. DYLAI haeriadau dadfygio ddilysu trefnu mewn adeiladau di-ryddhad.
QubEnvelope (fersiwn 0x01, heb ei lofnodi, pob maes dewisol yn absennol):
"body" (5 encoded bytes)
"qub_id" (7 encoded bytes)
"sig_alg" (8 encoded bytes)
"version" (8 encoded bytes)
"reply_to" (9 encoded bytes) ← only if present (reply chains)
"body_hash" (10 encoded bytes)
"unlock_at" (10 encoded bytes)
"created_at" (11 encoded bytes)
"outcome_at" (11 encoded bytes) ← only if present (V1.1 verdict mechanic)
"content_type" (13 encoded bytes)
"sender_label" (13 encoded bytes) ← only if present
"author_pubkey" (14 encoded bytes) ← only if present
"cosigner_pubkey" (16 encoded bytes) ← only if present (pact cosign)
"author_signature" (17 encoded bytes) ← only if present
"cosigner_signature" (19 encoded bytes) ← only if present (pact cosign)
Deilliad trefn allwedd QubEnvelope: mae pob allwedd yn llinyn testun CBOR. Hyd amgodedig = pennawd 1 byte + hyd y llinyn (ar gyfer llinynnau o dan 24 byte). Trefnwch yn ôl cyfanswm hyd amgodedig yn gyntaf, yna'n lecsicograffig ar gyfer allweddi o'r un hyd.
SealedQub (fersiwn 0x01, cyhoeddus, dim derbynnydd):
"title" (6 encoded bytes) ← only if present
"qub_id" (7 encoded bytes)
"version" (8 encoded bytes)
"unlock_at" (10 encoded bytes)
"outcome_at" (11 encoded bytes) ← only if present (V1.1 verdict mechanic)
"visibility" (11 encoded bytes)
"drand_round" (12 encoded bytes)
"drand_chain_id" (15 encoded bytes)
"recipient_pubkey" (17 encoded bytes) ← only if present
"tlock_ciphertext" (17 encoded bytes)
PactTerms (corff cytundeb, content_type 0x03):
"notes" (6 encoded bytes) ← only if present
"terms" (6 encoded bytes)
"title" (6 encoded bytes)
"party_a" (8 encoded bytes)
"party_b" (8 encoded bytes)
"pact_version" (13 encoded bytes)
PactTerm (rhes o'r arae terms):
"key" (4 encoded bytes)
"value" (6 encoded bytes)
PartyIdentifier (map party_a / party_b):
"label" (6 encoded bytes)
"contact" (8 encoded bytes) ← only if present
3.3 Cyfeirnod Amgodio Byte
| Math | Amgodiad CBOR | Enghraifft |
|---|---|---|
| Hash SHA3-256 (32 byte) | 0x58 0x20 + 32 byte |
body_hash, qub_id |
| Amserlinau (i64) | Math mawr 0 (positif) neu 1 (negatif), amgodiad byrraf | Eiliadau Unix |
| Fersiwn (u8, gwerth 1) | 0x01 (un byte) |
|
| Math cynnwys (u8, gwerth 1) | 0x01 (un byte) |
|
| sig_alg (u8, gwerth 0) | 0x00 (un byte) |
|
| Llofnod ML-DSA-65 (3,309 byte) | 0x59 0x0C 0xED + 3,309 byte |
author_signature, cosigner_signature |
| Allwedd gyhoeddus ML-DSA-65 (1,952 byte) | 0x59 0x07 0xA0 + 1,952 byte |
author_pubkey, cosigner_pubkey |
4. Deilliadau Normadol
4.1 qub_id
Mae'r qub_id yn adnabod qub yn unigryw ac yn rhwymo'r QubEnvelope i'r SealedQub. Mae'n cael ei ddeillio'n benderfynol o gynnwys yr amlen.
qub_id = SHA3-256(
"QUB_ID_V2" || // domain separator: ASCII bytes [0x51 0x55 0x42 0x5F 0x49 0x44 0x5F 0x56 0x32] (9 bytes) + 0x00 padding (1 byte) = 10 bytes
version || // u8 (1 byte)
content_type || // u8 (1 byte)
created_at || // i64 big-endian (8 bytes)
unlock_at || // i64 big-endian (8 bytes)
outcome_at_or_zero || // i64 big-endian (8 bytes; 0 when outcome_at is absent)
drand_round || // u64 big-endian (8 bytes)
body_hash || // [u8; 32] (32 bytes)
title_hash // [u8; 32] (32 bytes; absent-sentinel = [0u8; 32])
)
// Total preimage: 108 bytes → 32-byte output
Amgodio gwahanydd parth: Mae'r llinyn "QUB_ID_V2" yn 9 byte ASCII. Caiff un byte padin 0x00 ei atodi i gyrraedd 10 byte ar gyfer aliniad. RHAID i weithrediadau ddefnyddio'r 10 byte union hyn: [0x51, 0x55, 0x42, 0x5F, 0x49, 0x44, 0x5F, 0x56, 0x32, 0x00].
Amgodio outcome_at: Estynnodd V1.1 y preimage o 92 i 100 byte er mwyn plygu'r maes outcome_at dewisol i mewn i'r rhwymo. Caiff outcome_at absennol ei amgodio fel 8 byte sero; mae dilyswyr y protocol yn gwrthod outcome_at <= 0 ym mhob man fel na all yr arwydd hwn wrthdaro â gwerth dilys. Gweler §3.2 (fformat gwifren) a'r tasks/verdict-uplift-plan.md yn-y-goeden am y mecanwaith dyfarniad sy'n cymell y maes hwn.
Amgodio drand_round: Estynnodd V1.2 y preimage o 100 i 108 byte er mwyn plygu drand_round (y rownd drand darged, §4.3) i mewn i'r rhwymo, a chododd y gwahanydd parth i QUB_ID_V2. Mae hyn yn rhwymo rownd y clo amser i mewn i hunaniaeth y qub: ni all porth ail-rwymo'r cyphertext i rownd wahanol (e.e. un sydd eisoes wedi pasio) na'r hyn y mae'r unlock_at a ddangosir yn ei awgrymu. Mae'r weithdrefn datgloi (§8) hefyd yn dilysu bod y rownd sydd wedi'i phobi i mewn i stanza cyphertext tlock yn cyfateb i unlock_round(unlock_at), felly mae'r amser datgloi a ddangosir yn brofadwy yn rownd sy'n gatio'r datgryptio.
Priodweddau:
- Mae newid unrhyw faes yn y QubEnvelope (corff, amserlinau, math cynnwys, fersiwn) yn cynhyrchu qub_id gwahanol.
- Caiff y qub_id ei gyfrifo cyn amgryptio. Mae'r QubEnvelope a'r SealedQub yn cario'r un qub_id. Mae'r gwyliwr yn dilysu eu bod yn cyfateb ar ôl datgryptio.
- Nid yw qub_id yn dibynnu ar
sender_label,author_signature, nacauthor_pubkey. Mae hyn yn golygu bod yr un cynnwys wedi'i selio ar yr un pryd yn cynhyrchu'r un qub_id waeth pwy sy'n ei lofnodi. - Mae newid
titley SealedQub (gyda phopeth arall wedi'i sefydlogi) yn newidqub_idtrwytitle_hash. Felly ni all porth (gateway) gyfnewid y teitl plaen a ddangosir ar y cyfrif i lawr heb ddilysu hunaniaeth y qub. - Mae newid
outcome_aty SealedQub (gyda phopeth arall wedi'i sefydlogi) yn newidqub_idtrwy'r preimage. Ni all porth gyfnewid y dyddiad dyfarniad cyn-datgelu a ddangosir ar y cyfrif i lawr heb ddilysu hunaniaeth y qub. - Mae newid
drand_round(gyda phopeth arall wedi'i sefydlogi) yn newidqub_idtrwy'r preimage. Ni all porth ail-rwymo cyphertext y clo amser i rownd wahanol heb annilysu hunaniaeth y qub; ynghyd â gwiriad rownd-stanza amser-datgloi §8, mae'runlock_ata ddangosir yn rownd sy'n gatio'r datgryptio mewn gwirionedd.
4.2 body_hash
body_hash = SHA3-256(body)
Ble mae body yn llwyth tâl cynnwys Vec<u8> amrwd. Ar gyfer qubs testun, dyma yw corff y qub wedi'i amgodio UTF-8.
4.2.1 title_hash
title_hash = SHA3-256(NFC(title).utf8_bytes) if title is present
title_hash = [0u8; 32] if title is absent
Ble mae title yn deitl plaen dewisol a wynebir ar gyfrif i lawr y gwyliwr cyn datgelu (gweler §3.2). Mae normaleiddio NFC yn rhedeg ar amser hash fel bod y crynodeb yn sefydlog ar draws dilyniannau pwyntiau côd sy'n weledol-gyfartal. Mae'r sentinel cyfan-zerod wedi'i gadw ar gyfer yr achos absennol; mae llinyn gwag yn cael ei wrthod ar ffin CBOR safonol fel amgodiad an-safonol o "absennol" (mae'r amgodiad safonol yn hepgor y maes yn gyfan gwbl).
4.3 Mapio Rownd-Datgloi
drand_round = ceil((unlock_at - chain_genesis_time) / chain_period_seconds)
| Paramedr | Ffynhonnell | Enghraifft |
|---|---|---|
unlock_at |
Eiliadau Unix UTC a ddewiswyd gan y defnyddiwr | 1735689600 (2025-01-01 00:00:00 UTC) |
chain_genesis_time |
gwybodaeth cadwyn drand (genesis_time) |
1595431050 |
chain_period_seconds |
gwybodaeth cadwyn drand (period) |
30 |
Mae'r gweithred ceil() yn dewis y rownd drand gyntaf y mae ei hamser datgelu ≥ unlock_at. Mae hyn yn sicrhau nad yw'r qub yn dod yn datgryptiadwy cyn yr amser datgloi a ddewiswyd.
Achos ymylol: os yw (unlock_at - chain_genesis_time) yn union rannadwy gan chain_period_seconds, y canlyniad yw'r union rownd honno — mae'r qub yn datgloi'n union ar amser datgelu y rownd honno.
Dilysu: RHAID i unlock_at fod yn y dyfodol ar amser selio. RHAID i unlock_at BEIDIO â bod yn fwy na 10 mlynedd o created_at (i gyfyngu risg dibyniaeth drand-hir-orwel; DYLAI'r UI rybuddio ar gyfer dyddiadau datgloi y tu hwnt i 2 flynedd).
5. Newtypes Fformat Gwifren
Mae newtypes fformat gwifren yn darparu diogelwch amser-crynhoi rhag cymysgu bytes CBOR â JSON, testun plaen amrwd, neu amgodiadau byte eraill.
| Math | Yn Cynnwys | Cynhyrchwyd Gan | Defnyddir Gan |
|---|---|---|---|
SealedQubCbor |
CBOR safonol y SealedQub | serialize_sealed_qub() |
Uwchlwytho storfa parhaol, nôl gwyliwr |
QubEnvelopeCbor |
CBOR safonol y QubEnvelope | serialize_qub_envelope() |
Mewnbwn amgryptio tlock, allbwn datgryptio tlock |
5.1 Rheolau Adeiladu
// Production code — only through CBOR serialisers:
let sealed = SealedQubCbor::from_encoded(cbor_bytes);
// There is deliberately NO From<Vec<u8>> implementation.
// You cannot accidentally wrap arbitrary bytes in a wire format type.
// Accessing raw bytes:
let bytes: &[u8] = sealed.as_bytes();
let bytes: Vec<u8> = sealed.into_bytes();
5.2 Dilysu ar Adeiladu
DYLAI from_encoded() ddilysu bod y mewnbwn yn dechrau gyda phennawd map CBOR dilys. Mae dilysu strwythurol llawn yn digwydd ar amser parsio, nid amser adeiladu, er mwyn osgoi parsio-dwbl.
6. Cofrestrfa Math Cynnwys
| Gwerth | Math | Maint Corff Mwyaf | Nodiadau |
|---|---|---|---|
0x00 |
Wedi'i gadw (annilys) | — | RHAID PEIDIO â'i ddefnyddio |
0x01 |
Testun plaen (UTF-8, Markdown cyfyngedig) | 50 KB taledig / 10 KB am ddim | Gweler §10 am reolau rendro. Mae'r rhaniad rhad ac am ddim / taledig yn cael ei orfodi gan y gwasanaeth uwchlwytho; mae'r nenfwd caled-haen-protocol yn 50 KB. |
0x02 |
Wedi'i gadw (dyfodol) | — | Wedi'i ddyrannu ar gyfer math cynnwys yn y dyfodol; nid yw'n ddilys yn v1. RHAID i wylwyr ei wrthod fesul y rheol isod. |
0x03 |
Cytundeb (cytundeb dwyochrog, corff CBOR) | 100 KB | Mae'r corff yn PactTerms CBOR safonol (§6.1). Llofnodi cyd-arwyddwr fesul §9.7. |
0x04 |
Dyfarniad (hunan-raddio gan y crëwr, corff CBOR) | 8 KB | Mae'r corff yn VerdictBody CBOR safonol (§6.2). Allyrrir gan y bwriad verdict ochr-system yn unig. Mae'r berthynas rhiant ar y tag Arweave Parent-Tx-Id, nid ar y corff. Gweler verdict-uplift-plan §3.4. |
RHAID i wylwyr wrthod mathau cynnwys anhysbys gyda gwall clir-weladwy i'r defnyddiwr. RHAID i wylwyr BEIDIO â cheisio rendro mathau anhysbys fel testun.
6.1 Corff Cytundeb (content_type = 0x03)
Mae corff cytundeb yn amgodiad CBOR safonol o werth PactTerms:
PactTerms {
pact_version: u8, // 0x01 for structured/v1
title: String, // ≤ 200 bytes, NFC
terms: Vec<PactTerm>, // ≤ 20 rows
party_a: PartyIdentifier, // initiator
party_b: PartyIdentifier, // counter-signer
notes: Option<String>, // ≤ 5,000 bytes, NFC; absent key if none
}
PactTerm { key: String (≤ 100), value: String (≤ 2,000) } // NFC on both sides
PartyIdentifier{ label: String (≤ 100), contact: Option<String (≤ 320)> }
Rhoddir trefnau allwedd CBOR safonol y tri map yn §3.2. RHAID i gyfanswm CBOR cytundeb wedi'i gyfresoli BEIDIO â mynd y tu hwnt i 100 KB (yn cyfateb â §6).
Gwahaniaethydd sgema. RHAID i'r rhes gyntaf yn terms ar gyfer cytundeb structured/v1 fod yn { key: "pact_schema", value: "structured/v1" }. Mae rhesi heb yr arwydd hwn yn gytundebau "personol" ac nid ydynt yn derbyn dilysu strwythuredig na rendro sgema-ymwybodol.
Tyllau cydnabyddiaeth wedi'u rhewi. Mae cytundebau structured/v1 yn cario'n union bedair rhes cydnabyddiaeth o dan yr allweddi hyn:
"initiator_standard_terms"
"initiator_capacity_terms"
"counterparty_standard_terms"
"counterparty_capacity_terms"
Mae'r value ar gyfer pob un yn un o wyth llinyn Saesneg wedi'u rhewi a ddewiswyd gan y pâr (rôl, math), ble mae rôl ∈ { seller, buyer, provider, client } a math ∈ { standard, capacity }. Mae'r llinynnau eu hunain yn ddata protocol normadol — mae llofnodion ML-DSA-65 y ddau barti yn ymrwymo i'r bytes union trwy body_hash. NID ydynt wedi'u lleoleiddio; mae'r corff wedi'i lofnodi yn iaith-niwtral. Mae unrhyw newid geiriad yn gofyn am fersiwn sgema newydd (structured/v2).
Mae'r wyth llinyn, eu chwilio (acknowledgement_for(role, kind)), a'r rhesymeg ar gyfer pob un wedi'u pinio gan y gweithrediad cyfeirio. RHAID i weithrediadau cydymffurfiol allyrru gwerthoedd cydnabyddiaeth byte-fath; mae profion hash-corff SHA3-256 ffigwr-aur sy'n cwmpasu pob un o'r pedwar cyfuniad rôl yn dal unrhyw ddrifft.
Trefn arddangos y gwyliwr. Mae'r llinynnau cydnabyddiaeth yn cynnwys ymadroddion fel "described above", sy'n rhagdybio bod y rhesi disgrifiad / cwmpas yn rendro o flaen y cydnabyddiaethau. RHAID i wylwyr rendro'r arae terms yn nhrefn CBOR; mae ail-drefnu yn torri semanteg y rhyddiaith.
Cyswllt y gwrthbarti. Pan fydd contact Parti B yn gyfeiriad e-bost dilys, mae'r gwasanaeth uwchlwytho qub yn anfon e-bost gwahoddiad adolygu / cyd-arwyddo yn awtomatig ar amser llwyfannu ac yn rhwymo'r cyd-arwydd terfynol i ddilysu'r un cyfeiriad hwnnw (§9.7). Gellir cyd-arwyddo cytundebau y mae cyswllt Parti B yn absennol ynddynt, ond dim ond trwy sianel allan-o-fand — mae'r gwasanaeth yn gwrthod ceisiadau cyd-arwyddo na allant gynhyrchu marciwr dilysu-e-bost 15-munud cyfatebol.
6.2 Corff Dyfarniad (content_type = 0x04)
Mae corff dyfarniad yn amgodiad CBOR safonol o werth VerdictBody:
VerdictBody {
verdict_version: u8, // 0x01 for structured/v1
outcome: u8, // 1=Right · 2=Partial · 3=Wrong · 4=Unfalsifiable
reflection: Option<String>, // ≤ 2,000 bytes NFC; "what changed, what did you learn"
evidence_url: Option<String>, // ≤ 2,048 bytes; HTTPS only; absent key when omitted
}
Trefn allwedd CBOR safonol:
"outcome" (8 encoded bytes)
"reflection" (11 encoded bytes) ← only if present
"evidence_url" (13 encoded bytes) ← only if present
"verdict_version" (16 encoded bytes)
RHAID i gyfanswm CBOR dyfarniad wedi'i gyfresoli BEIDIO â mynd y tu hwnt i 8 KB (yn cyfateb â'r rhes gofrestrfa uchod).
Enwm canlyniad. Mae'r byte gwifren yn fwriad-niwtral; mae'r pedwar bwced Right / Partial / Wrong / Unfalsifiable yn cwmpasu gofod canlyniad pob bwriad sy'n dwyn dyfarniad. Mae labeli fesul-bwriad ("Wedi'i alw'n iawn" / "Fe'i cedwais" / "Wedi'i gyflenwi" / "Wedi'i gadarnhau" ar gyfer Right, ac yn y blaen) yn fater rendro ochr-y-gwyliwr a ddatrysir yn erbyn bwriad y qub rhiant — mae'r wifren yn aros yn iaith- a bwriad-niwtral. RHAID gwrthod gwerthoedd y tu allan i 1..=4 wrth ddatgodio.
Cyswllt â'r rhiant. NID yw qub dyfarniad yn cario'r cyfeirnod rhiant yn ei gorff. Allyrrir id trafodiad Arweave y qub rhiant fel y tag storio Parent-Tx-Id ar amser uwchlwytho (haen tag storio §7). Mae hyn yn cadw'r corff yn ddatganiad llofnodedig hunangynhwysol o hunan-asesiad; sefydlir y gadwyn archwilio ("iawn am beth?") trwy'r chwiliad-tag Arweave.
Diogelwch URL tystiolaeth (normadol). Pan fydd evidence_url yn bresennol, RHAID i ddilyswyr (ochr-cyfansoddi, ochr-wifren, ymyl y Worker) orfodi:
- HTTPS yn unig. RHAID i'r llinyn ddechrau gyda'r dilyniant beit
https://. Caiff unrhyw gynllun arall —http,ftp,javascript,data,file, ac yn y blaen — ei wrthod. - Cap hyd. ≤ 2,048 beit (terfyn URL ymarferol y porwr).
- Gwiriad NFC + nodbwynt gelyniaethus. Yr un rheol â
titleareflection— gwrthodir nodbwyntiau bidi-override / lled-sero / tag-bloc / BOM / C0 / C1. Mae'r diffiniad yn cyfateb i'rcrate::handle::contains_hostile_text_codepointRust ac i'rworkers/api/src/utils/unicode.ts::isHostileCodepointTS (cadwch nhw mewn cydgam). - Dim gofod gwyn, dim rheolyddion ASCII. Gwrthodir gofod gwyn / DEL / beitiau is-
0x20unrhyw le yn yr URL — yn cau'r fector chwistrellu\n/\tnad yw'r rheol bidi yn ei orchuddio. - Segment gwesteiwr nad yw'n wag. RHAID i bopeth rhwng
https://a'r/,?, neu#cyntaf fod yn anwag.
Dim nôl ochr-gweinydd. RHAID i'r Worker BEIDIO â dirprwyo, nôl, na rhagolygu'r URL. Mae'r protocol yn storio llinyn; mae'r rendro'n digwydd ochr-y-gwyliwr gyda rel="nofollow noopener noreferrer" target="_blank" a gwesteiwr gweladwy wedi'i arddangos ochr yn ochr â thestun y ddolen.
Myfyrdod. Testun myfyrdod dewisol wedi'i ysgrifennu gan y crëwr ("beth a newidiodd, beth a ddysgoch"). Yr un dilysu NFC + nodbwynt gelyniaethus â title. Mae mewnbwn gwag / gofod-gwyn yn unig yn cwympo i absennol ar amser adeiladu.
Fersiwn sgema. Mae v1 yn cefnogi verdict_version = 0x01 yn unig. Mae diwygiadau sgema yn y dyfodol yn codi'r beit hwn ac yn glanio ochr yn ochr â fersiwn protocol newydd fesul §12.
7. Protocol Selio
Y dilyniant selio cyflawn. Mae pob cam yn normadol.
1. User composes plaintext and metadata in ComposeQub.
2. Validate:
a. body is non-empty.
b. body size ≤ max for content_type and user tier (see §6).
c. unlock_at is in the future.
d. unlock_at ≤ created_at + 10 years.
e. content_type is a known, supported value.
3. Compute body_hash = SHA3-256(body).
4. Set created_at = current Unix seconds UTC.
5. Select drand chain. Load chain_genesis_time and chain_period_seconds, and
compute drand_round = ceil((unlock_at - chain_genesis_time) / chain_period_seconds).
(Computed here, before qub_id, because drand_round is bound into the qub_id
preimage — §4.1, V1.2.)
6. Compute qub_id (see §4.1), folding in drand_round from step 5.
7. Construct QubEnvelope with all fields.
8. Serialise QubEnvelope using canonical CBOR → bytes B.
Assert: serialised output matches canonical profile (§3).
9. Compute C = tlock_encrypt(B, drand_round, drand_chain_public_key).
10. Construct SealedQub with tlock_ciphertext = C, and matching qub_id, version,
unlock_at, drand_chain_id, drand_round.
12. Serialise SealedQub using canonical CBOR → SealedQubCbor.
12a. Generate K = 32 random bytes (CSPRNG) and N = 12 random bytes (CSPRNG).
Compute W = wrap_sealed_qub(SealedQubCbor, qub_id=qub_id, key=K, nonce=N)
per §13. The bytes uploaded to permanent storage are the OuterWrapper CBOR W,
never the bare SealedQubCbor. K leaves the device only as the URL
fragment in step 16.
13. Display seal-time disclosure. User confirms.
14. Validate upload eligibility via the qub upload service (bot-detection, entitlement, rate limits).
15. Submit W (the OuterWrapper bytes) to the qub upload service; the service
signs and uploads to permanent storage. The service is byte-blind to the inner
SealedQubCbor and never receives K.
16. Receive arweave_tx_id from the service. Construct delivery URL as
`<origin>/c/<arweave_tx_id>#<base64url(K)>` (or `<origin>/s/<short_code>#<base64url(K)>`
when a short code is allocated). Browsers do not transmit URL fragments
to servers, so K is never observed by qub.social or any storage gateway.
Haen tagiau storfa (allan-o-fand). Mae'r gwasanaeth uwchlwytho qub yn atodi set o dagiau trafodion storfa sydd wedi'u cadw'n fwriadol fach ochr yn ochr â'r llwyth tâl wedi'i amlapio. Mae Content-Type=application/octet-stream yn ofynnol yn normadol. Mae'r gwasanaeth cyfeirio yn atodi tri thag dewisol ychwanegol pan fydd y crëwr yn dewis eu wynebu: Intent (bwriad cyfansoddi wedi'i ddilysu yn erbyn rhestr ganiataol — e.e., quote, reply, commitment), Author (ôl-bys allwedd-gyhoeddus §9.3 y crëwr fel hecs llythrennau bach 64-cymeriad), a Parent-Tx-Id (ID trafodyn storfa y qub rhiant ar gyfer cadwyni ateb, base64url 43-cymeriad).
Mae'r tag Author yn dewis-i-mewn fesul qub: mae ap creu cyfeirio yn ei atodi dim ond pan fydd y defnyddiwr yn galluogi priodoli cyhoeddus yn benodol ar amser selio. Pan fydd y togl i ffwrdd — y rhagosodiad — nid oes tag Author yn cael ei ysgrifennu ac mae'r qub yn anbriodol ar y gadwyn: nid oes dim mewn storfa parhaol yn cysylltu'r uwchlwythiad â handlen, e-bost, na qubs eraill crëwr. Pan fydd y togl ymlaen, mae ôl-bys Author yn datrys i @handle dewisedig y crëwr trwy gadwyn dystiolaeth §9.5. Mae perthnasoedd cadwyn-ateb ac Intent yn an-adnabyddol. Mae'r amlapio allanol (§13) yn amddiffyn corff mewnol rhag cydberthynas cyphertext — gan atal cynaeafwr rhag adnabod a swmp-ddatgryptio uwchlwythiadau ar siâp qub ar ôl i'w rownd drand gyhoeddi.
NID yw'r gwasanaeth cyfeirio yn atodi tagiau App-Name, App-Version, neu Type yn fwriadol: byddai unrhyw hidlydd gwerth-unigol o'r fath yn dychwelyd y corpws qub cyfan i ymholiad GraphQL, sy'n anghyson â chwmpas cyfrinachedd-corff-yn-unig yr amlapio.
RHAID i ddilyswr cydymffurfiol BEIDIO â dibynnu ar unrhyw dag storfa ar gyfer dilysu trydydd-parti §11; mae'r hash corff / qub_id / llofnod yn ymrwymo dim ond i'r CBOR mewnol, byth i'r set tagiau.
8. Protocol Datgloi
Y dilyniant datgloi cyflawn. Mae pob cam yn normadol.
1. Viewer opens delivery URL. Extract arweave_tx_id from path AND
K = base64url_decode(fragment) from the URL fragment. If the fragment
is absent or malformed → display "this URL is missing its decryption
key" and stop; the viewer MUST NOT contact the storage gateway
without K, since fetching wrapped bytes the viewer cannot decrypt
serves no purpose and only leaks the access attempt.
2. Check denylist. If tx_id is denylisted → display block message. Stop.
3. Fetch OuterWrapper bytes from permanent storage (with multi-gateway fallback).
3a. Unwrap: parse the bytes as OuterWrapper (§13), verify the wrapper
`version` byte is `0x01`, and compute SealedQubCbor =
unwrap_sealed_qub(OuterWrapper, key=K). Any AEAD authentication
failure (wrong K, tampered ciphertext, swapped qub_id-as-AAD,
swapped nonce) → display "this URL's decryption key does not match
the stored qub" and stop. Authentication failures are
indistinguishable to the viewer per §13.5.
4. Parse SealedQubCbor → SealedQub.
5. Validate: SealedQub.version is known (0x01). Reject unknown versions.
6. If current time < SealedQub.unlock_at → display countdown. Poll or wait.
6a. Round-binding check (V1.2). Recompute expected_round =
ceil((SealedQub.unlock_at - chain_genesis_time) / chain_period_seconds).
Reject unless SealedQub.drand_round == expected_round AND the round baked
into the tlock ciphertext stanza (read via the age/tlock header, no signature
required) == expected_round. The stanza round is the one that actually gates
decryption; without this check a malicious creator could bind the ciphertext
to an already-past round while displaying a future countdown, so anyone
reading the stored bytes could decrypt before unlock_at. Implementations with
no chain identity (test mocks) skip this check.
7. Once current time ≥ SealedQub.unlock_at:
a. Fetch drand round signature for SealedQub.drand_round from drand network.
b. Compute B = tlock_decrypt(SealedQub.tlock_ciphertext, round_signature).
8. Parse B → QubEnvelope.
9. Validate QubEnvelope.version is known.
10. Verify: SHA3-256(QubEnvelope.body) == QubEnvelope.body_hash.
Fail → integrity error.
11. Verify: QubEnvelope.qub_id == SealedQub.qub_id.
Fail → integrity error.
12. Verify: QubEnvelope.unlock_at == SealedQub.unlock_at.
Fail → integrity error.
13. Verify: QubEnvelope.content_type is known and renderable.
Known values: 0x01 (text), 0x03 (pact). Unknown → display error.
14. If QubEnvelope.sig_alg != 0x00 → verify author signature (see §9.4).
15. If cosigner_pubkey or cosigner_signature present → verify cosigner (see §9.7).
16. Render content using appropriate renderer (see §10 for text, §6 for pact).
17. Construct RevealedQub for display.
9. Llofnodi Awduriaeth
9.1 Rhesymeg
Caiff qubs eu storio mewn storfa parhaol. RHAID i lofnodion awduriaeth aros yn anffugadwy yn ddiderfyn, sef pam mae v1.0 yn defnyddio'r cynllun ôl-gwantwm ML-DSA-65 (FIPS 204) yn hytrach na chynllun clasurol y gallai ei ddiogelwch ddirywio o fewn oes parhaol y qub.
9.2 Cofrestrfa Algorithm
sig_alg |
Cynllun | Maint Allwedd | Maint Llofnod |
|---|---|---|---|
0x00 |
Dim llofnod (heb ei lofnodi) | — | — |
0x01 |
ML-DSA-65 (FIPS 204) | 1,952 byte | 3,309 byte |
RHAID i wylwyr wrthod gwerthoedd sig_alg anhysbys.
9.3 Adeiladu Preimage wedi'i Lofnodi
sig_input = SHA3-256(
"QUB_AUTHOR_SIG_V1" || // domain separator (17 bytes)
version || // u8 (1 byte)
qub_id || // [u8; 32] (32 bytes)
body_hash || // [u8; 32] (32 bytes)
unlock_at || // i64 big-endian (8 bytes)
0x00 // u8 (1 byte): MUST be 0x00 in v1.0
)
// Total preimage: 91 bytes → 32-byte hash
signature = Sign(author_secret_key, sig_input)
Gwahanydd parth: mae "QUB_AUTHOR_SIG_V1" yn 17 byte ASCII: [0x51, 0x55, 0x42, 0x5F, 0x41, 0x55, 0x54, 0x48, 0x4F, 0x52, 0x5F, 0x53, 0x49, 0x47, 0x5F, 0x56, 0x31]. Dim padin.
Byte olynol: RHAID i'r 91ed byte preimage fod yn 0x00. Mae'r gweithrediad cyfeirio yn datgelu hyn fel y cysonyn ORG_ID_PRESENT_INDIVIDUAL = 0x00 yn crates/qub-core/src/signing.rs; RHAID i wylwyr sy'n ailadeiladu sig_input ar gyfer dilysu allyrru'r un byte.
Cwmpas llofnod — beth sydd ac nad yw'n cael ei orchuddio. Mae sig_input yn ymrwymo i bedwar maes amlen: version, qub_id, body_hash, unlock_at (yn ogystal â'r gwahanydd parth sefydlog a'r byte org_id_present). Mae tri o'r pedwar yn ddi-ymyriadau strwythurol: mae qub_id ei hun yn deillio o version, content_type, created_at, unlock_at, outcome_at, drand_round, a body_hash trwy preimage §4.1, felly mae unrhyw newid i'r meysydd hynny yn cynhyrchu qub_id gwahanol ac yn annilysu'r llofnod yn drosglwyddadwy. Felly'r wyneb wedi'i ardystio'n uniongyrchol yw:
| Maes | Wedi'i ardystio gan lofnod | Sut |
|---|---|---|
version |
✓ | Mewnbwn uniongyrchol i sig_input |
qub_id |
✓ | Mewnbwn uniongyrchol |
body_hash |
✓ | Mewnbwn uniongyrchol |
unlock_at |
✓ | Mewnbwn uniongyrchol |
content_type |
✓ | Yn drosglwyddadwy, trwy preimage qub_id |
created_at |
✓ | Yn drosglwyddadwy, trwy preimage qub_id |
outcome_at |
✓ | Yn drosglwyddadwy, trwy preimage qub_id |
drand_round |
✓ | Yn drosglwyddadwy, trwy preimage qub_id (V1.2) |
body |
✓ | Yn drosglwyddadwy, trwy body_hash = SHA3-256(body) |
author_pubkey |
— (ymhlyg) | Yr allwedd a ddilysodd y llofnod yw'r awdur, drwy ddiffiniad |
sender_label |
✗ | Testun arddangos-yn-unig; cyfnewidiol heb dorri'r llofnod |
reply_to |
✗ | Pwyntydd edafu; cyfnewidiol heb dorri'r llofnod |
cosigner_pubkey / cosigner_signature |
— | Wedi'u llofnodi'n annibynnol dros yr un sig_input (gweler §9.7) |
drand_chain_id, tlock_ciphertext, visibility |
— | Meysydd allanol SealedQub, nid o fewn yr amlen — wedi'u gorchuddio gan eu di-ymyriadau strwythurol eu hunain (cysondeb rownd / cadwyn) ond nid gan lofnod yr awdur. (Mae drand_round bellach wedi'i rwymo'n drosglwyddadwy trwy preimage qub_id — gweler uchod.) |
Goblygiadau diogelwch meysydd heb eu hardystio.
- Gallai parti gyda mynediad ysgrifennu i'r bytes wedi'u storio gyfnewid
sender_label("Alice" → "Mallory") heb annilysu llofnod yr awdur. Mae'rauthor_pubkeyy tu mewn i'r amlen yn parhau i fod yn angor hunaniaeth gwirioneddol — RHAID i wylwyr ddeillio'r hunaniaeth arddangos oauthor_pubkey(trwy haen dystiolaeth §9.5) yn hytrach na thrystiosender_label. - Gellir golygu maes
reply_toyn yr un modd ar ôl llofnodi. Oherwydd bodqub_idyn cynnwys-cyfeiriedig, ni all ymosodwr bwyntioreply_toat darged nad yw'n bodoli, ond gallant ail-rieni ateb yn dawel i qub gwahanol sy'n bodoli.
RHAID i weithrediadau sy'n arddangos sender_label neu reply_to i ddefnyddwyr terfynol wynebu'r hunaniaeth wedi'i hardystio (ôl-bys allwedd gyhoeddus, tystiolaeth) fel y prif arwydd hunaniaeth, nid y label.
9.4 Gweithdrefn Dilysu
1. Read sig_alg from QubEnvelope.
2. If sig_alg == 0x00 → unsigned. No verification. Display "unsigned qub."
3. If sig_alg is unknown → reject. Display "unrecognised signature scheme."
4. Extract author_signature and author_pubkey. If either is absent → integrity error.
5. Reconstruct sig_input using fields from QubEnvelope (same formula as §9.3).
6. Verify(author_pubkey, sig_input, author_signature).
7. If verification succeeds → display "signed by [key fingerprint]."
8. If verification fails → display "signature verification failed."
Dilysu llofnod yw'r weithred ddrutaf (yn enwedig ML-DSA-65). DYLAI gael ei berfformio ar ôl i'r holl wiriadau rhatach (hash, qub_id, unlock_at) basio.
9.5 Tystiolaethau Hunaniaeth
Mae tystiolaethau hunaniaeth — mapio'r author_pubkey i honiadau hunaniaeth dynol-adnabyddadwy fel dolen qub, cyfeiriad e-bost, dolen gymdeithasol, neu gymhwyster passkey — yn welliant cynyddol ochr-gwyliwr ac NID yn ofynnol ar gyfer dilysu llofnod. RHAID i wylwyr sy'n datrys tystiolaethau i hunaniaeth arddangos roi'r flaenoriaeth:
handle > email > social > fingerprint
Mae'r ôl-gwymp ôl-bys yn hecs llythrennau bach SHA3-256(author_pubkey); mae bob amser ar gael ar gyfer unrhyw qub wedi'i lofnodi. CAIFF gwylwyr ei dalfyrru ar gyfer ei arddangos — mae'r gwyliwr cyfeirio yn rendro qub: wedi'i ddilyn gan y pedwar byte cyntaf a'r pedwar byte olaf (qub:<8 hex>…<8 hex>).
Gall dilyswr cydymffurfiol gwblhau pob gwiriad yn §9.4 heb gysylltu â'r API qub, heb unrhyw rwydwaith y tu hwnt i storfa parhaol a drand, a heb unrhyw chwilio ochr-gweinydd. Mae datrys tystiolaeth yn gam ymdrech-orau ar wahân a berfformir dim ond ar ôl i ddilysu llofnod lwyddo.
9.6 Effaith Maint
| Ed25519 | ML-DSA-65 | |
|---|---|---|
| Llofnod | 64 byte | 3,309 byte |
| Allwedd gyhoeddus | 32 byte | 1,952 byte |
| Cyfanswm fesul qub | 96 byte | 5,261 byte |
| Delta cost storfa (ar ~$5/MB) | ~$0.0005 | ~$0.026 |
Ar gyfer qub testun o 500–2,000 byte, mae ML-DSA-65 yn treblu'r maint wedi'i storio yn fras. Mae'r gost absoliwt yn ddibwys.
9.7 Dilysu Cyd-arwyddwr (Cytundebau Dwyochrog Cytundeb)
Ar gyfer cytundebau dwyochrog (content_type = 0x03), mae ail haen lofnod yn profi bod y ddau barti wedi cydsynio i'r un telerau.
Meysydd amlen:
cosigner_pubkey: Allwedd gyhoeddus ML-DSA-65 y cyd-arwyddwr (Parti B).cosigner_signature: Llofnod dros yr unsig_inputâ'r awdur (§9.3).
RHAID i'r ddau faes fod yn bresennol gyda'i gilydd neu'r ddau yn absennol. Os yw union un yn bresennol, RHAID i wylwyr riportio gwall cywirdeb.
Gweithdrefn dilysu:
1. If cosigner_pubkey absent and cosigner_signature absent → no cosigner. Done.
2. If exactly one is present → integrity error.
3. Verify cosigner_pubkey != author_pubkey (prevent self-cosigning).
Fail → display "cosigner pubkey must differ from author."
4. Reconstruct sig_input using the same formula as §9.3.
5. Verify(cosigner_pubkey, sig_input, cosigner_signature).
6. Success → display "co-signed by [cosigner fingerprint]."
7. Failure → display "co-signature verification failed."
Priodweddau:
- Mae'r cyd-arwyddwr yn llofnodi'r un
sig_inputâ'r awdur — mae'r ddau barti'n ymrwymo i'r unqub_id,body_hash, acunlock_at. - NID yw deilliad
qub_id(§4.1) yn cynnwys meysydd cyd-arwyddwr. Nid yw ychwanegu cyd-arwyddwr at amlen sy'n bodoli yn newid yqub_id. - Gall cytundeb fod wedi'i lofnodi gan yr awdur yn unig (ymrwymiad un-ochrog), cyd-arwyddwr yn unig (anarferol), neu'r ddau (prawf dwyochrog llawn).
Gât-rhwymo-e-bost (gweithredol). Pan fydd cytundeb wedi'i lwyfannu yn cario cyswllt e-bost Parti B (§6.1), RHAID i'r gwasanaeth uwchlwytho qub wrthod y cais cyd-arwyddo oni bai bod marciwr dilysu-e-bost byrhoedlog yn bodoli sy'n cyfateb i'r ID llwyfannu a hash-e-bost-wedi'i-normaleiddio'r cyswllt hwnnw. Caiff y marciwr ei ysgrifennu gan /api/v1/auth/verify pan fydd y tocyn dolen-hud yn cario staging_id a bod y cyfeiriad wedi'i ddilysu yn cyfateb i SHA-256(normalise_email(party_b.contact)) — ble mae normalise_email(addr) yn cadw cas y rhan leol ac yn lleihau'r rhan parth yn unig (yn unol â RFC 5321 §2.3.11), ac mae SHA-256 yma yn hash NIST FIPS 180-4 (gwahanol i'r SHA3-256 a ddefnyddir mewn deilliadau §4) — ac yn dod i ben 900 eiliad (15 munud) ar ôl cyhoeddi. Mae hyn yn gât gwrth-ddynwarediad gweithredol, NID yn rhan o brawf qub ar-y-gadwyn — mae dilyswr trydydd-parti sy'n ailchwarae §11 angen dim ond storfa parhaol a drand, heb unrhyw chwilio ochr-gweinydd. Mae'r marciwr yn bodoli ar yr ochr gweinydd yn unig ac nid yw byth yn rhan o'r corff wedi'i lofnodi.
Effaith maint (awdur ML-DSA-65 + cyd-arwyddwr):
| Cydran | Maint |
|---|---|
| Llofnod awdur | 3,309 byte |
| Allwedd gyhoeddus awdur | 1,952 byte |
| Llofnod cyd-arwyddwr | 3,309 byte |
| Allwedd gyhoeddus cyd-arwyddwr | 1,952 byte |
| Cyfanswm gorbenion crypto | 10,522 byte |
| Delta cost storfa | ~$0.05 |
10. Rendro a Glanhau Markdown
Mae'r adran hon yn ddiogelwch-feirniadol. Mae'r gwyliwr yn rendro qubs testun (content_type = 0x01) gan ddefnyddio is-set Markdown cyfyngedig.
10.1 Elfennau a Ganiateir
- Penawdau:
#trwy####(dim#####nac######) - Pwyslais: trwm (
**), italig (*), trwy-rwygiad (~~) - Rhestrau: trefnedig (
1.) ac anhrefnedig (-,*) - Dyfynfeydd (
>) - Côd: rhychwantau mewnlinell (```) a blociau wedi'u ffensio (`````)
- Llinellau llorweddol (
---) - Toriadau llinell (dwy ofod olynol neu linell wag)
- Paragraffau
10.2 Elfennau Gwaharddedig
| Elfen | Trin |
|---|---|
HTML amrwd (<div>, <script>, ac ati) |
Wedi'i ddileu'n gyfan gwbl. Nid oes HTML yn pasio drwodd. |
Delweddau () |
Wedi'u dileu. Mae cystrawen delweddau yn cael ei dynnu o'r allbwn. |
Dolenni ([text](url)) |
URL wedi'i rendro fel testun plaen gweladwy. Heb ei auto-gysylltu. Heb fod yn glic-adwy heb gamau defnyddiwr penodol. |
| Cynlluniau URL peryglus | javascript:, data:, vbscript:, file: — wedi'u dileu. |
| Iframes, embeds, gwrthrychau | Wedi'u dileu. |
| Endidau HTML | Wedi'u datgodio i nodau arddangos dim ond os yw'n ddiogel. |
10.3 Gweithrediad
RHAID i weithrediadau ddefnyddio parseu rhestr ganiataol llym, nid rhestr-bloc. Y dull a argymhellir:
- Parsio Markdown gan ddefnyddio
pulldown-cmark(neu gyfwerth). - Cerdded yr AST a gollwng unrhyw nod nad yw yn y rhestr ganiataol (§10.1).
- Ar gyfer nodau dolen: allyrru'r URL fel testun gweladwy, nid fel elfen
<a>y gellir ei chlicio. - Trosi'r AST wedi'i hidlo i gynrychioliad canol-gam wedi'i deipio (e.e., enum
MarkdownNodegydag amrywiadau diogel yn unig). Mae HTML amrwd yn strwythurol an-gynrychioliadwy yn y IR hwn. - Rendro o'r IR wedi'i deipio i'r haen olwg targed (e.e., cydrannau golwg adweithiol, nodau DOM). Dim cydgysylltiad llinyn HTML na
innerHTMLar unrhyw bwynt.
Mae dulliau rhestr-bloc yn fregus oherwydd gall estyniadau Markdown newydd neu cwirciau parser gyflwyno elfennau heb eu hidlo. Mae'r dull AST-wedi'i-deipio yn gwneud XSS yn strwythurol amhosibl — nid oes amrywiad sy'n gallu cario HTML mympwyol.
10.4 Cyfyngiadau Maint a Strwythur
- Dyfnder pennawd a renderir mwyaf:
####(H4). Mae#####a dyfnach yn cael eu rendro fel testun trwm. - Dim cyfyngiad ar nifer paragraffau (cyfyngiadau maint corff yn §6 yw'r cyfyngiad).
- Blociau côd wedi'u ffensio: dim amlygu cystrawen yn MVP. Wedi'u rendro fel testun cyn-fformatiedig monospace.
11. Dilysu Trydydd Parti
Gall unrhyw drydydd parti ddilysu qub cyhoeddus heb gydweithrediad qub. Y weithdrefn dilysu:
1. Obtain arweave_tx_id (from delivery URL or direct knowledge).
2. Fetch SealedQubCbor from any storage gateway.
3. Confirm storage block inclusion (block height, block timestamp).
4. Parse SealedQubCbor → SealedQub.
5. Fetch drand round signature for SealedQub.drand_round.
6. tlock_decrypt(tlock_ciphertext, round_signature) → QubEnvelope CBOR bytes.
7. Parse → QubEnvelope.
8. Verify SHA3-256(body) == body_hash.
9. Verify QubEnvelope.qub_id == SealedQub.qub_id.
10. Verify QubEnvelope.unlock_at == SealedQub.unlock_at.
11. If sig_alg != 0x00: verify author_signature (see §9.4).
12. All checks pass → qub is verified.
Beth mae dilysu yn ei brofi:
| Prawf | Beth y mae'n ei sefydlu |
|---|---|
| Ymrwymiad | Roedd y cyphertext yn bodoli erbyn amserlen bloc y storfa. |
| Cywirdeb | Mae'r corff testun plaen yn cyfateb i'r hash wedi'i ymrwymo ac nid yw wedi cael ei newid. |
| Amseru | Roedd y cynnwys yn anddarllenadwy tan rownd drand, sy'n cyfateb i'r amser datgloi a ddewiswyd (yn amodol ar dybiaethau diogelwch tlock a drand). |
Beth NAD yw dilysu yn ei brofi:
| An-brawf | Pam |
|---|---|
| Awduriaeth | Mae'r sender_label yn addurnol. Heb sig_alg ≥ 0x01, gallai unrhyw un fod wedi selio'r cynnwys hwn. |
| Bwriad | Mae'r qub yn profi cynnwys ac amseru, nid yr hyn a olygai'r crëwr yn oddrychol. |
| Amseru cyn-digwyddiad | Gall cynhwysiad bloc y storfa fod ar ei hôl hi i uwchlwythiad gwirioneddol o funudau. Amser y bloc yw amserlen yr ymrwymiad, nid yr eiliad y pwysodd y defnyddiwr "selio." |
12. Fersiynu
12.1 Fersiwn Protocol
Mae'r maes version (u8) yn SealedQub a QubEnvelope yn adnabod prif fersiwn y protocol.
- RHAID i wylwyr wrthod prif fersiynau anhysbys gyda gwall clir.
- GALL prif fersiynau hysbys oddef meysydd dewisol anhysbys os yw rheolau cydnawsedd ymlaen yn caniatáu (mae meysydd dewisol absennol o'r drefn allwedd safonol yn cael eu hanwybyddu).
- Mae mathau cynnwys (
content_type) a chynlluniau llofnod (sig_alg) wedi'u gatio gan fersiwn: gellir cyflwyno gwerthoedd newydd dim ond ochr yn ochr â fersiwn protocol newydd neu ddiweddariad cofrestrfa penodol.
12.2 Hanes Fersiwn
| Fersiwn | Gwerth | Disgrifiad |
|---|---|---|
| v1 | 0x01 |
Qubs testun cyhoeddus (content_type 0x01), cytundebau dwyochrog cytundeb (0x03, sgema structured/v1, awdur ML-DSA-65 + cyd-arwyddwr), tlock, SHA3-256 |
12.3 Cydnawsedd Ymlaen
DYLAI gwyliwr v1 sy'n dod ar draws QubEnvelope gydag allweddi map CBOR dewisol anhysbys (allweddi nad ydynt yn y drefn safonol §3.2) anwybyddu'r allweddi hynny a pharhau â dilysu gan ddefnyddio meysydd hysbys. Mae hyn yn caniatáu ychwanegiadau bach yn y dyfodol (e.e., metadata newydd) heb angen cynnydd prif fersiwn.
DYLAI gwyliwr v1 sy'n dod ar draws sig_alg = 0x01 (ML-DSA-65) ond heb gefnogaeth dilysu ML-DSA-65 arddangos cynnwys y qub gyda hysbysiad "llofnod yn bresennol ond nid yn ddilysadwy", nid gwrthod y qub yn gyfan gwbl. Mae'r gweithrediad cyfeirio heddiw yn gwrthod pob gwerth sig_alg heblaw 0x00 ac 0x01 oherwydd nad oes algorithm dilys arall yn y gofrestrfa v1 — mae gwrthodiad llym a meddal-fethu yn arsylladwy-fath nes bod trydydd algorithm yn cael ei gofrestru. Mae'r ymddygiad meddal-fethu uchod yn dod yn lwyth-eredig unwaith y mae §9.2 yn derbyn cofnod newydd, ac fe ddiweddarir y gwyliwr cyfeirio i feddal-fethu ar y pwynt hwnnw.
12.4 Fersiwn Amlapio Allanol
Mae'r OuterWrapper a ddisgrifir yn §13 yn cario ei byte version ei hun, annibynnol ar SealedQub.version a QubEnvelope.version. Mae'r ddau ofod fersiwn yn esblygu ar wahân: mae amnewid cymesur diogel-ôl-gwantwm yn y dyfodol yn codi'r byte amlapio heb gyffwrdd â fersiwn y protocol mewnol, ac mae ychwanegiad haen-protocol yn y dyfodol (e.e., maes amlen newydd) yn codi'r fersiwn fewnol heb gyffwrdd â'r byte amlapio.
OUTER_WRAPPER_VERSION_* |
Gwerth | Algorithm | Statws |
|---|---|---|---|
OUTER_WRAPPER_VERSION_1 |
0x01 |
AES-256-GCM gyda nonce 12-byte, tag dilysu 16-byte, AAD wedi'i rwymo i qub_id |
rhagosodiad v1 |
| — | 0x02–0xFF |
Wedi'u cadw | Dyfodol |
RHAID i wylwyr wrthod fersiynau amlapio anhysbys gyda gwall clir. Mae'r protocol yn cadw'r gofod fersiwn amlapio yn fwriadol gul nes bod gyrrwr ymfudo concrid yn ymddangos (e.e., arweiniad NIST yn ffafrio AEAD gwahanol); dyrannir slot 0x02 yn yr un diwygiad sy'n cyflwyno'r algorithm.
13. Amlapio Amgryptio Allanol
13.1 Rhesymeg
Mae haenau'r protocol (QubEnvelope → tlock → SealedQub) yn gwneud qub wedi'i selio yn wedi'i gloi-amser: mae'r corff yn anddarllenadwy tan unlock_at ac mae llofnod rownd drand wedi'i gyhoeddi. Ar ôl datgloi, fodd bynnag, mae llofnod y rownd yn gyhoeddus ac mae siâp CBOR safonol SealedQub yn adnabyddadwy, felly gallai cynaeafwr a fynegeiodd drafodion storfa parhaol swmp-ddatgryptio'r corpws qub cyfan.
Mae'r amlapio amgryptio allanol yn cau'r sianel honno trwy interposio haen AEAD gymesur ychwanegol rhwng yr SealedQubCbor safonol a'r bytes wedi'u hysgrifennu i storfa parhaol. Mae'r allwedd 256-bit K yn byw dim ond yn ffragment URL y ddolen drosglwyddo ac ar ddyfeisiau defnyddwyr; nid yw porwyr yn trosglwyddo ffragmentau URL i weinyddion, felly mae qub.social, pob porth storfa, a phob CDN o flaen y naill na'r llall yn arsylladwy-ddall i K. Mae pob qub mewn storfa parhaol felly'n cyphertext ansafonol y mae ei destun plaen yn anadferadwy heb yr URL a ddewisodd y crëwr ei rannu.
Effaith net:
- Imiwnedd rhifo trwy ragosodiad. Mae bytes wedi'u hamlapio mewn storfa parhaol yn anwahaniaethol o ran byte oddi wrth cyphertext mympwyol. Nid yw strategaeth cynaeafwr o "GraphQL-ymholiad am uwchlwythiadau ar siâp qub, swmp-ddatgryptio gyda llofnodion drand cyhoeddus" yn dod i ben gyda thestun plaen.
- Ystum preifatrwydd crypto-malu. All qub.social yn llythrennol ddim datgryptio ei gorpws ei hun. Mae gwysion yn cyrraedd cyphertext, nid testun plaen.
- Ysgol cyfrinachedd dwy-haen. Rhagosodiad = mynediad wedi'i reoli gan ddolen (yr adran hon). Mae qubs preifat wedi'u hamgryptio i'r derbynnydd (nodwedd Cam 2 wedi'i chadw, heb ei manylu eto) yn haenu ar ben fel yr ail haen.
13.2 Haenu
plaintext body ← QubEnvelope.body (§2.2)
↓ canonical CBOR (§3)
envelope CBOR
↓ tlock encrypt to drand round (§7 step 10)
tlock_ciphertext (inside SealedQub) (§2.3)
↓ canonical CBOR (§3)
SealedQubCbor bytes ← inner wire artifact
↓ AES-256-GCM(K, nonce, AAD=qub_id) (§7 step 12a, this section)
OuterWrapper CBOR bytes ← uploaded to permanent storage (§7 step 15)
Mae selio a datgloi yn yr haen protocol (§7, §8) yn ddigyfnewid o dan ffin yr amlapio; mae'r amlapio yn ymgysylltu ar safle galwad seal() ac yn datgysylltu ar safle galwad unlock().
13.3 Strwythur Data OuterWrapper
struct OuterWrapper {
version: u8, // 0x01, see §12.4
qub_id: [u8; 32], // copied from inner SealedQub; AEAD AAD
nonce: [u8; 12], // 96-bit AEAD nonce
ciphertext: Vec<u8>, // AES-256-GCM(K, nonce, SealedQubCbor, AAD=qub_id) || 16-byte tag
}
Diymyriadau maes.
- RHAID i
versionfod yn0x01ar gyfer bytes amlapio v1.0. - RHAID i
qub_idgyfateb i faesqub_idy SealedQub a adferir ar ôl dadamlapio. Nid yw'r cam dadamlapio yn gorfodi hyn yn uniongyrchol (mae rhwymo AAD AEAD yn gwneud ymyrraeth lefel-byte yn amhosibl), ond mae'r haen datgloi yn gwirio'r berthynas yn drosglwyddadwy: os bydd crëwr yn amlapioSealedQubCborna fydd eiqub_idmewnol yn cyfateb iqub_idyr amlapio, mae §8 cam 11 yn methu. - RHAID i
noncefod yn 96 bit (12 byte), wedi'i gynhyrchu o'r newydd gan CSPRNG ar gyfer pob gweithred amlapio. Mae ailddefnyddio nonce o dan yr un allwedd yn caniatáu ymosodiadau ailddefnyddio-nonce AEAD sy'n adfer y testun plaen; RHAID i gynhyrchwyr drin parau (key,nonce) fel un-saethiad. - Mae
ciphertextyn allbwn AES-256-GCM: bytes cyphertext wedi'u cydgysylltu gyda thag dilysu 16-byte.ciphertext.len() == SealedQubCbor.len() + 16yn union.
Amgodio CBOR. CBOR safonol fesul §3, gyda'r un rheol trefnu-allweddi (wedi'i drefnu yn ôl hyd byte amgodedig yn esgynnol, yna'n lecsicograffig). Y pedair allwedd yw:
| Allwedd | Bytes amgodedig | Trefn |
|---|---|---|
nonce |
6 | 1 |
qub_id |
7 | 2 |
version |
8 | 3 |
ciphertext |
11 | 4 |
Mae byte cyntaf CBOR y OuterWrapper felly'n bennawd map o hyd pendant ar gyfer map 4-cofnod (0xA4).
13.4 Rhwymo AAD i qub_id
Mae'r amlapio yn rhwymo qub_id fel data ardystiedig ychwanegol AEAD. Dyma'r amddiffyn strwythurol llwyth-eredig yn erbyn tair dosbarth o ymosodiad:
| Ymosodiad | Amddiffyn |
|---|---|
Symud cyphertext o dan faes qub_id gwahanol yn yr amlapio |
Annhebygrwydd AAD → mae dilysu AEAD yn methu |
| Cymysgu ffragment URL qub A gyda bytes storfa parhaol qub B | Annhebygrwydd AAD → mae dilysu AEAD yn methu |
Ymyrryd â maes qub_id yr amlapio ar ôl uwchlwytho |
Annhebygrwydd AAD → mae dilysu AEAD yn methu |
Nid yw cario qub_id yn nhestun plaen yr amlapio yn gwanhau imiwnedd rhifo'n ystyrlon — mae qub_id ei hun yn hash SHA3-256 o preimage §4.1 heb preimage adferadwy o'r crynodeb, ac mae rhifwr a gynaeafodd y bytes amlapio yn barod yn dysgu dim o'r qub_id gweladwy na allent fynd amdano o fodolaeth yr uwchlwythiad ei hun.
13.5 Algorithmau Amlapio a Dadamlapio
wrap_sealed_qub(SealedQubCbor S, qub_id Q, key K, nonce N):
require K.len() == 32 and N.len() == 12 and Q.len() == 32
C := AES_256_GCM_encrypt(key=K, nonce=N, msg=S, aad=Q)
// C includes the 16-byte authentication tag at the end
return canonical_cbor_encode(OuterWrapper{
version: 0x01,
qub_id: Q,
nonce: N,
ciphertext: C,
})
unwrap_sealed_qub(OuterWrapper bytes W, key K):
require K.len() == 32
O := canonical_cbor_decode(W) as OuterWrapper
require O.version == 0x01 // §12.4
P := AES_256_GCM_decrypt(
key=K, nonce=O.nonce, ciphertext=O.ciphertext, aad=O.qub_id
)
// any AEAD failure → DECRYPT_FAILED, indistinguishable to caller
return P // P is the inner SealedQubCbor
Cwymp modd-methiant. Mae K anghywir, nonce anghywir, annhebygrwydd AAD, a cyphertext sydd wedi'i ymyrryd â hi, i gyd yn cynhyrchu'r un gwall DECRYPT_FAILED. Priodwedd AEAD bwriadol yw hwn: byddai gwahaniaethu'r modd methiant yn creu sianel ochr y gallai ymosodwr o bell ei brofio trwy anfon amlapiadau anffurfiol ac amseru'r ymateb. RHAID i weithrediadau cyfeirio gwympo pob methiant AEAD i un siâp gwall.
13.6 Deunydd Allwedd a Dosbarthu
Mae'r allwedd amlapio K yn werth hap-unffurf 256-bit a gynhyrchwyd fesul-qub gan CSPRNG. Mae'r gweithrediadau cyfeirio yn ei ffynonellu o:
- Crëwr WASM:
getrandom(WebCrypto o dan y backendwasm_js). - Llwybr selio ochr-gweinydd Worker:
crypto.getRandomValues.
Dosbarthu: RHAID amgodio K fel base64 diogel-URL (RFC 4648 §5, dim padin) a'i atodi i'r ddolen drosglwyddo fel y cydran ffragment:
delivery_url = <origin>/c/<arweave_tx_id>#<base64url(K)>
Nid yw'r ffragment byth yn cael ei drosglwyddo i unrhyw weinydd gan borwr cydymffurfiol. Mae sianeli adfer (mynegai hanes ochr-gweinydd, anfon-awtomatig e-bost dewis-i-mewn) sy'n cadw'r ddolen drosglwyddo lawn — gan gynnwys y ffragment — y tu hwnt i ddyfais y defnyddiwr yn fasnach benodol yn erbyn yr ystum crypto-malu rhagosodedig a RHAID iddynt gael eu gatio ar gydsyniad defnyddiwr penodol.
Colled ffragment. Os bydd defnyddiwr yn colli ffragment yr URL ac nad oes ganddo unrhyw sianel adfer, mae'r qub yn anddarllenadwy. Hwn yw'r fasnach llwyth-eredig yn y dyluniad a RHAID iddo gael ei ddatgelu i'r defnyddiwr ar amser selio. Mae'r MVP yn cryfhau'r datgeliad amser-selio gyda chopi "cadwch yr URL hwn" penodol a sianel adfer e-bost-wedi'i-ddilysu i ddefnyddwyr sy'n dewis i mewn.
13.7 Allan-o-Gwmpas ar gyfer yr Adran Hon
- Mae llofnodi awduriaeth (§9) yn ddigyfnewid: caiff llofnodion eu cyfrifo y tu mewn i'r
QubEnvelopemewnol ac maent yn cael eu hadfer ar ôl dadamlapio → datgryptio tlock → parsio CBOR. - Mae qubs preifat wedi'u hamgryptio i'r derbynnydd (nodwedd Cam 2 wedi'i chadw, heb ei manylu eto) yn cyfansoddi ar ben yr amlapio hwn fel ail haen cyfrinachedd; gall y ddwy haen fod yn weithredol ar yr un pryd.
- Mae cytundebau (§6, content_type
0x03) yn cael eu hamlapio yn union fel qubs testun; mae'r amlapio yn ddall-byte i'r math cynnwys mewnol.
13.8 Qubs cyhoeddus (hepgor amlapio)
Mae'r amlapio allanol yn ddewisol ar yr haen drosglwyddo. Gall crëwr selio qub fel un cyhoeddus, ac yn yr achos hwnnw caiff yr SealedQubCbor safonol ei ysgrifennu i storfa parhaol yn uniongyrchol, heb unrhyw haen OuterWrapper a heb unrhyw allwedd K:
SealedQubCbor bytes ──(public)──▶ uploaded to permanent storage as-is
SealedQubCbor bytes ──(private)─▶ AES-256-GCM(K, …) ▶ OuterWrapper ▶ uploaded
Mae qub cyhoeddus wedi'i gloi-amser ond heb ei gatio gan ddolen: mae'n aros yn anddarllenadwy tan i'w rownd drand gyhoeddi (mae'r haen tlock yn ddigyfnewid), ond ar ôl datgloi gall unrhyw un sydd â'r arweave_tx_id ei ddatgryptio — nid oes angen ffragment URL, oherwydd nad oes K. Hon yw'r fasnach fwriadol ar gyfer arwynebau y mae'n rhaid i'r gweinydd eu gyrru: mae e-byst hysbysu-datgelu, embeds trydydd-parti, a SEO cyfoethocach ar ôl datgelu i gyd angen dolen sy'n gweithio heb gyfrinach nad yw'r gweinydd byth yn ei dal (§13.6).
Canlyniadau y mae'n RHAID i gynhyrchydd eu hystyried:
- Dim imiwnedd rhifo. Mae qubs cyhoeddus yn fforffedu priodwedd imiwnedd-rhifo §13.1 trwy adeiladwaith. Mae'r gwasanaeth uwchlwytho cyfeirio yn stampio tag storfa parhaol
Visibility: publicarnynt (ac arnynt hwy yn unig) fel eu bod yn ddarganfyddadwy yn fwriadol; nid yw qubs preifat yn cario tag o'r fath ac maent yn cadw eu hanwahaniaethedd o ran byte. - Teitl plaen wedi'i ddinoethi ar amser selio. Mae maes
title§3.2 yn destun plaen y tu mewn iSealedQubCbor. O dan yr amlapio mae wedi'i guddio tan i wyliwr gyflenwiK; heb yr amlapio mae'n ddarllenadwy gan y byd ar storfa parhaol o eiliad yr uwchlwytho, cyn datgloi. RHAID i apiau crëwr cydymffurfiol ddatgelu hyn ar amser selio. - Mae canfod yn strwythurol. Mae gwyliwr/embed cydymffurfiol yn gwahaniaethu'r ddau siâp trwy barsio: mae bytes sy'n parsio fel
OuterWrapperyn cymryd y llwybr dadamlapio-gyda-K; mae bytes sy'n parsio felSealedQubCbornoeth yn cael eu derbyn yn uniongyrchol. Nid oes angen unrhyw faner wifren, ac nid ywqub_idyn rhwymo gwelededd — mae'r un cynnwys yn unfath o ran byte ar haenSealedQubp'un a yw wedi'i selio'n gyhoeddus neu'n breifat.
Mae preifat (wedi'i amlapio) yn aros yn rhagosodiad; mae cyhoeddus yn ddewis crëwr penodol fesul-qub.
14. Fectorau Prawf
14.1 Deilliad qub_id
Input:
version = 0x01
content_type = 0x01
created_at = 1735689600 (2025-01-01 00:00:00 UTC)
unlock_at = 1736294400 (2025-01-08 00:00:00 UTC)
outcome_at = absent
drand_round = 4695445 (= (1736294400 - 1595431050) / 30, drand mainnet params §14.2)
body = "Hello, future." (UTF-8, 14 bytes)
title = absent
Intermediate:
body_hash = SHA3-256("Hello, future.")
= 76ab8b3f843c6ed4f2d0fd75b9f457b4
ad49dd4450f9c22723ae430e3af3211d
title_hash = [0u8; 32] (title absent — §4.2.1 sentinel)
Domain separator (10 bytes):
[0x51, 0x55, 0x42, 0x5F, 0x49, 0x44, 0x5F, 0x56, 0x32, 0x00]
Preimage (108 bytes — V1.2):
domain_separator || // 10 bytes
0x01 || // version
0x01 || // content_type
0x0000000067748580 || // created_at as i64 big-endian (1735689600)
0x00000000677DC000 || // unlock_at as i64 big-endian (1736294400)
0x0000000000000000 || // outcome_at_or_zero (outcome_at absent)
0x000000000047A595 || // drand_round as u64 big-endian (4695445)
body_hash || // 32 bytes
title_hash // 32 bytes (all-zeros sentinel; title absent)
Expected output:
qub_id = SHA3-256(preimage)
= 3a9fcb31b750d985c262fada6d4f777f
d6a28be831d941d85c131f5a4bbaf8a4
RHAID i weithrediadau gynhyrchu gwerthoedd body_hash a qub_id union yr un fath ar gyfer y mewnbwn hwn. DYLAI'r fector prawf hwn fod y prawf uned cyntaf a ysgrifennir. Cyfrifwyd y gwerthoedd safonol uchod gan y gweithrediad cyfeirio a RHAID iddynt gyfateb bit-am-bit. Cynlluniau preimage hanesyddol (cyn-lansio — nid oedd unrhyw qubs byw yn dibynnu arnynt): y qub_id V1.0 92-byte oedd 3d9fc2390eab043d38a1669ed3b71be76f9eefe872b9569ab1aaa027b88392b0; y qub_id V1.1 100-byte (ar ôl plygu outcome_at_or_zero i mewn) oedd b0d032898ad629795150fdcb3f84e518f59ed05b7a2a82bc24ebdb87f52144ed. Mae V1.2 yn plygu drand_round i mewn ac yn codi'r gwahanydd parth i QUB_ID_V2.
14.2 Mapio Rownd-Datgloi
Input:
unlock_at = 1735689600
chain_genesis_time = 1595431050
chain_period_seconds = 30
Calculation:
(1735689600 - 1595431050) / 30 = 4675285.0
ceil(4675285.0) = 4675285
drand_round = 4675285
14.3 Tro Cylch CBOR Safonol
RHAID i weithrediadau ddilysu bod serialize(parse(serialize(qub))) == serialize(qub) ar gyfer pob mewnbwn dilys. Mae hwn yn brawf priodwedd, nid yn fector sengl.
14.4 CBOR PactTerms (content_type 0x03)
Input:
pact_version = 1
title = "Scooter deposit"
terms = [
{ key: "Item", value: "Honda Metropolitan scooter" },
{ key: "Price", value: "$100" },
{ key: "Deposit", value: "$10" }
]
party_a = { label: "Alice" }
party_b = { label: "Bob", contact: "bob@example.com" }
notes = absent
Canonical CBOR key order (PactTerms):
"notes"(6) < "terms"(6) < "title"(6) < "party_a"(8) < "party_b"(8) < "pact_version"(13)
Canonical CBOR key order (PactTerm):
"key"(4) < "value"(6)
Canonical CBOR key order (PartyIdentifier):
"label"(6) < "contact"(8)
Cyfrifir y bytes CBOR safonol a'r body_hash SHA3-256 gan y gweithrediad cyfeirio. RHAID i weithrediadau gynhyrchu CBOR byte-fath ar gyfer y mewnbwn hwn.
RHAID i weithrediadau hefyd ddilysu bod serialize(parse(serialize(pact))) == serialize(pact) ar gyfer pob mewnbwn PactTerms dilys (prawf priodwedd).
14.5 Fectorau Traws-Iaith Amlapio Allanol
Mae gan yr amlapio allanol (§13) ffigwr safonol ar wahân ar crates/qub-core/tests/vectors/wrapper_v1.json. Mae pob achos yn sefydlogi tupl (key, nonce, qub_id, sealed_cbor) fel mewnbynnau hecs di-ddehongli ac yn haeru allbwn expected_wrapper_hex penodol. Mae'r ddau weithrediad cyfeirio'n defnyddio'r un ffeil JSON:
- Rust:
crates/qub-core/tests/wrapper_vectors.rs(cargo test -p qub-core --test wrapper_vectors). - TypeScript:
workers/api/src/crypto/__tests__/wrapper.test.ts(npm test).
Mae'r ffigwr ar hyn o bryd yn pinio tri achos:
| Achos | Cwmpas |
|---|---|
basic-text-public |
Y siâp SealedQub realistig lleiaf; dim meysydd dewisol. Yn sefydlu siâp amlapio safonol ar gyfer qub typig v1.0. |
with-recipient-pubkey |
SealedQub gyda recipient_pubkey wedi'i osod (llwybr Cam 2). Set allwedd CBOR mewnol gwahanol, qub_id gwahanol. |
longer-body |
Corff ~4 KiB — yn ymarfer ragddodiaid hyd CBOR aml-byte y tu mewn i'r amlen mewnol a'r cyphertext allanol. |
RHAID i weithrediadau gynhyrchu expected_wrapper_hex byte-fath ar gyfer y mewnbynnau a recordiwyd. Mae adfywio'r ffigwr yn gofyn QUB_REGEN_VECTORS=1 cargo test -p qub-core --test wrapper_vectors ac mae wedi'i gadw ar gyfer newidiadau fformat bwriadol.
15. Llywodraethu Proffil Crypto (Dyfodol)
Mae'r adran hon yn wybodaethol ar gyfer v1 ac yn dod yn normadol y tro cyntaf y mae ail algorithm yn dod i mewn i unrhyw un o primitifau cryptograffig qub.
15.1 Ystum Cyfredol
Mae protocol v1 yn rhwymo'n union un algorithm fesul primitif:
- Llofnod: ML-DSA-65 (
sig_alg = 0x01; allwedd gyhoeddus 1952-byte, llofnod 3309-byte) a heb ei lofnodi (sig_alg = 0x00). Nid yw'r gofrestrfa §9.2 yn diffinio unrhyw werthoedd eraill; RHAID i ddilysydd v1 wrthod pobsig_algy tu allan i{0x00, 0x01}. Rhagwelir cofnod Ed25519 yn y dyfodol (§15.3) ond nid yw wedi'i ddyrannu yn v1. - Cloi-amser: drand quicknet yn unig — mae hash y gadwyn, yr allwedd gyhoeddus, amser geni a chyfnod yn baramedrau rhwydwaith sefydlog a gariwyd gan y
DrandTimelockProvider::quicknet()cyfeirio (crates/qub-core/src/tlock.rs) aconfig/drand-endpoints.json. - Amlapio allanol: AES-256-GCM v1 yn unig (§13).
Mae dilyswyr ar hyn o bryd yn caled-godio hydoedd allwedd a llofnod fesul primitif. Nid oes unrhyw wyneb hyblygrwydd yn cael ei amlygu gan y fformat gwifren.
15.2 Siâp Bwriadedig
Pan fydd ail algorithm yn dod i mewn i'r protocol, caiff y dilyswr ei gyflunio ar gyfer CryptoProfile enwedig (e.e., ExqubV1) sy'n rhestru'r set union o werthoedd a ganiateir fesul primitif — sig_algs, cadwyni drand, fersiynau amlapio, mathau cynnwys. Mae'r proffil yn sefydlog ar amser dilysu, byth wedi'i negodi yn-band. Mae unrhyw werth y tu allan i'r proffil gweithredol yn cael ei wrthod.
Mae hyn yn gwarantu na all ychwanegu ML-DSA-87 nac actifadu Ed25519 wanhau cyfluniadau dilysu sy'n bodoli yn ôl-weithredol: mae dilyswr v1 yn aros yn ddilyswr v1 hyd yn oed ar ôl i broffil v2 gael ei gyhoeddi.
15.3 Amodau Sbarduno
Hyrwyddwch §15 i statws normadol pan gynigir unrhyw un o'r canlynol:
- Ail byte
sig_alg(actifadu Ed25519, ML-DSA-87, neu unrhyw gofnod newydd yn y gofrestrfa §9). - Ail gadwyn drand mewn defnydd cynhyrchu.
- Ail fersiwn amlapio allanol.
Hyd hynny mae §15 yn ddalwr lle sy'n sefydlogi siâp yr ymfudo fel bod PRs y dyfodol yn glanio yn erbyn targed hysbys yn hytrach nag ail-ddadlau'r wyneb negodi o'r dechrau.