# PVUGC-010: CRS Validation **Issue Code:** PVUGC-010 **Title:** CRS Validation and Binding Verification **Severity:** 🟒 Low **Status:** βœ… Resolved **Report Version:** 4.0 (Final) **Review Round:** 4 (Final) **Dates:** Identified 2025-10-07 (v1.0); Resolved 2025-10-07 (v2.0); Peer Reviewed 2025-10-26 **Reviewers:** M1 (preliminary + update); M2 (mathematician deep-dive); Crypto-Reviewer (final review) **Cross-References:** - [`PVUGC-2025-10-05.md Β§10 Binding CRS Requirements (SXDH/DLIN) Β§89-91 (lines 208-210)`](../PVUGC-2025-10-05) - [`report-preliminary-2025-10-07/PVUGC-010-crs-validation.md`](../report-preliminary-2025-10-07/PVUGC-010-crs-validation) (v1.0) - [`report-update-2025-10-07/PVUGC-010-crs-validation.md`](../report-update-2025-10-07/PVUGC-010-crs-validation) (v2.0) - [Appendix A10.M101](APPENDIX-issue-debates.md#a10-m101) (Binding CRS verification essentials) - [Appendix A10.CR01](APPENDIX-issue-debates.md#a10-cr01) (VK subgroup validation gap) --- ## Executive Summary **Verdict:** βœ… **Resolved** - v2.0 binding CRS requirement with digest pinning is cryptographically sound. M2's canonical validation algorithm provides complete, implementable specification. **Impact:** Prevents acceptance of non-binding (witness-indistinguishable) CRS that would break GS soundness (PVUGC-002) and enables CRS substitution attacks. CRS digest pinning in the context chain prevents post-arming CRS replacement. **Changes:** - v1.0: Identified underspecified "tag mechanism" (line 190), status Open - v2.0: Added binding CRS requirement (SXDH/DLIN), pairing check `e(u₁, v₁) β‰  e(uβ‚‚, vβ‚‚)`, digest pinning in `GS_instance_digest`, multi-CRS defense (Β§89-91, lines 208-210) - Peer Review: Validated v2.0 resolution, provided canonical `ValidateCrsAndComputeDigest` algorithm with 5-stage validation (parsing, subgroup checks, binding check, digest computation, test vectors), expanded test vectors (3β†’11), reference implementation, ceremony protocol, verification tooling **Remaining gaps:** - No normative algorithm in main specification (only principles stated) - Implementation guidance needed (ceremony best practices, verification tools) - Test vector suite required for interoperability - CRS ceremony audit trail unspecified **Required action:** Add M2's canonical algorithm as Β§92 in [`PVUGC-2025-10-20.md Β§1 Introduction`](../PVUGC-2025-10-20) with normative (MUST) requirements for binding verification, constant-time comparison, and subgroup membership checks. Publish reference test vectors (minimum 11 cases). Provide ceremony best practices and verification tool. --- ## Security Parameters | Parameter | Value | Justification | |-----------|-------|---------------| | Elliptic Curve | BLS12-381 | 128-bit security, Type-3 pairing support | | Pairing Type | Type-3 (𝔾₁ Γ— 𝔾₂ β†’ 𝔾_T) | Required for SXDH assumption | | Hash Function (Digest) | SHA-256 | 128-bit collision resistance | | Hash Function (KDF) | Poseidon2 | ZK-friendly, 128-bit security | | CRS Mode | SXDH Binding | Computational soundness under DDH | | Multi-CRS Count | β‰₯ 2 | Defense-in-depth, ceremony independence | | Ceremony Threshold | 1-out-of-n honest | Powers-of-Tau trust model | **Security Level:** 128-bit (quantum pre-image security: ~64-bit) --- ## Spec Location **Primary:** [`PVUGC-2025-10-05.md Β§10 Binding CRS Requirements (SXDH/DLIN)`](../PVUGC-2025-10-05) (Β§89-91) - Line 210: "Runtime MUST reject non-binding CRS via a tag embedded in `GS_instance_digest`" - Line 86: "`GS_instance_digest`" freeze requirement - Line 91-92: Multi-CRS AND-ing with digest pinning **Secondary:** - [`PVUGC-2025-10-05.md Β§10 Binding CRS Requirements (SXDH/DLIN)`](../PVUGC-2025-10-05) (`header_meta` includes `GS_instance_digest`) - [`PVUGC-2025-10-05.md Β§10 Binding CRS Requirements (SXDH/DLIN)`](../PVUGC-2025-10-05) (Lemma 1: GS product determinism requires binding CRS) - [`PVUGC-2025-10-05.md Β§10 Binding CRS Requirements (SXDH/DLIN)`](../PVUGC-2025-10-05) (`AD_core` includes `GS_instance_digest`) --- ## History (v1.0 β†’ v2.0 β†’ Peer Review) ### v1.0 Original Concern (2025-10-07) **Status:** πŸ”“ Open | **Severity:** 🟒 Low **Problem identified by M1:** - Line 190 states: "Runtime MUST reject non-binding CRS via a tag embedded in GS_instance_digest" - **Critical gaps:** - Tag format completely unspecified - Validation procedure undefined (how to check binding vs. WI?) - Embedding mechanism unclear - Forgery risk: attacker could create fake tag appearing binding - No reference implementation or test vectors **Security risks:** - **Risk 1:** Accept non-binding (WI) CRS β†’ GS commitments malleable β†’ soundness break (PVUGC-002) - **Risk 2:** Malicious CRS with trapdoor β†’ bypass "valid proof exists" requirement - **Risk 3:** Implementation incompatibility β†’ reject valid binding CRS (liveness failure) - **Risk 4:** CRS substitution attack β†’ replace honest CRS with malicious one **M1's assessment:** Low severity assuming honest CRS ceremony, but HIGH if ceremony compromised. Procedural controls mitigate but cryptographic enforcement needed. ### v2.0 Mitigation (2025-10-07) **Status:** βœ… Resolved | **Severity:** 🟒 Low β†’ Resolved **Normative changes in [`PVUGC-2025-10-05.md Β§10 Binding CRS Requirements (SXDH/DLIN)`](../PVUGC-2025-10-05):** **1. Explicit Binding Requirement (Β§89-91, line 210):** ``` Production deployments MUST use binding GS-CRS (SXDH or DLIN) Rejected: Witness-indistinguishable (WI), perfectly hiding, malleable CRS ``` **2. Binding Verification Mechanism (line 210):** ``` Binding CRS structure (SXDH, Type-3 pairing): - Basis vectors: (u₁, uβ‚‚) ∈ 𝔾₁ Γ— 𝔾₁ - Dual vectors: (v₁, vβ‚‚) ∈ 𝔾₂ Γ— 𝔾₂ - Pairing check: e(u₁, v₁) β‰  e(uβ‚‚, vβ‚‚) [non-orthogonal] Non-binding (WI) structure: - Perfectly orthogonal: e(u₁, vβ‚‚) = e(uβ‚‚, v₁) = 1 ``` **3. CRS Digest Pinning (Β§89-91, lines 86, 91-92):** ``` GS_instance_digest β†’ header_meta β†’ arming_pkg_hash β†’ ctx_hash β†’ KDF Security: Different CRS β†’ different digest β†’ different ctx_hash β†’ different K Result: Attacker cannot substitute CRS after arming (decryption fails) ``` **4. Multi-CRS Defense-in-Depth (Β§89-91, line 92):** ``` MUST: Minimum 2 independent binding GS-CRS transcripts Both digests pinned in GS_instance_digest AND-of-2: M_i^{AND} = ser(M_i^(1)) || ser(M_i^(2)) Security: Must compromise ALL ceremonies simultaneously ``` **Eliminated risks:** - βœ… No non-binding CRS acceptance (pairing check rejects WI) - βœ… No CRS substitution (digest chain prevents replacement) - βœ… No tag forgery (hash includes CRS data, verification includes pairing check) - βœ… Multi-CRS amplification (ceremony compromise requires collusion) ### Peer Review: M2's Canonical Algorithm (2025-10-15) **Contribution:** Complete, normative validation algorithm **M2's analysis ([Appendix A10.M101](APPENDIX-issue-debates.md#a10-m101)):** - **Verdict:** βœ… Resolved and Formally Validated - **Gap identified:** v2.0 principles correct but no unified algorithm (implementation variance risk) - **Deliverable:** Canonical `ValidateCrsAndComputeDigest` pseudocode with 5 stages **Algorithm stages:** 1. **Parse and structurally validate:** Deserialize CRS data, handle errors 2. **Subgroup and identity checks:** Point-on-curve, subgroup membership (cofactor clearing), reject identity elements 3. **Binding property check:** Compute `e(u₁, v₁)` and `e(uβ‚‚, vβ‚‚)`, verify inequality (constant-time) 4. **Canonical digest computation:** Hash with domain separation `"PVUGC/GS-CRS/v1"` 5. **Return success:** Accept with digest or reject with reason **Test vectors provided (3 β†’ 11 cases):** - Test Case 1: Valid binding CRS β†’ ACCEPT with digest - Test Case 2: Invalid non-binding (WI) CRS β†’ REJECT "CRS is not binding (p1 == p2)" - Test Case 3: Malformed CRS β†’ REJECT "Point not on curve" or "Invalid CRS serialization" - **Extended by Crypto-reviewer:** 11 comprehensive test cases covering all algorithm paths, side-channel tests, multi-CRS, cross-curve attacks **M2's validation:** Principles of v2.0 resolution are correct. Canonical algorithm eliminates implementation ambiguity and ensures security + interoperability. ### Final Review: Crypto-Reviewer Validation (2025-10-26) **Contribution:** Comprehensive report with formal proofs, expanded test coverage, implementation guidance **Crypto-reviewer's analysis:** - **Mathematical validation:** 4 formal theorems with proofs (binding detection, WI rejection, CRS binding, multi-CRS security) - **Test expansion:** 3 β†’ 11 test vectors with novel categories (wrong curve, side-channel timing) - **Reference implementation:** Production-quality Rust code with constant-time primitives - **Ceremony protocol:** Complete 3-phase MPC specification with security considerations - **Verification tooling:** CLI tool specification with JSON output and transcript validation - **Audit trail:** Complete JSON schema for ceremony documentation **M2's Round 3 validation:** - **Overall verdict:** βœ… APPROVED with Minor Revisions - **4 required revisions:** All incorporated in this final report - **3 optional enhancements:** Partially incorporated (security parameters table, test templates) --- ## Findings ### Finding 1: V2.0 Resolution is Cryptographically Sound **Evidence:** - Binding CRS requirement (SXDH/DLIN) is correct primitive for GS soundness - Pairing check `e(u₁, v₁) β‰  e(uβ‚‚, vβ‚‚)` correctly distinguishes binding from WI CRS - Digest pinning in context chain prevents substitution attacks - Multi-CRS AND-ing provides defense-in-depth **Formal validation:** **Theorem 1 (Binding CRS Detection):** For Type-3 pairing `e: 𝔾₁ Γ— 𝔾₂ β†’ 𝔾_T`, a GS-CRS `(u₁, uβ‚‚, v₁, vβ‚‚)` is binding under SXDH if and only if `e(u₁, v₁) β‰  e(uβ‚‚, vβ‚‚)`. *Proof (detailed):* **[Binding β†’ Inequality]** Assume CRS is binding under SXDH. By GS construction (EUROCRYPT 2008, Β§3.2), binding CRS satisfies: ``` u₁ = Ξ±Β·G₁ + G₁' and uβ‚‚ = Ξ²Β·G₁ + G₁' for Ξ± β‰  Ξ² v₁ = Gβ‚‚ + Ξ±Β·Gβ‚‚' and vβ‚‚ = Gβ‚‚ + Ξ²Β·Gβ‚‚' ``` where (G₁, G₁') ∈ 𝔾₁² and (Gβ‚‚, Gβ‚‚') ∈ 𝔾₂² are basis vectors. By bilinearity of pairing: ``` e(u₁, v₁) = e(Ξ±Β·G₁ + G₁', Gβ‚‚ + Ξ±Β·Gβ‚‚') = e(Ξ±Β·G₁, Gβ‚‚) Β· e(Ξ±Β·G₁, Ξ±Β·Gβ‚‚') Β· e(G₁', Gβ‚‚) Β· e(G₁', Ξ±Β·Gβ‚‚') = e(G₁, Gβ‚‚)^Ξ± Β· e(G₁, Gβ‚‚')^(Ξ±Β²) Β· e(G₁', Gβ‚‚) Β· e(G₁', Gβ‚‚')^Ξ± e(uβ‚‚, vβ‚‚) = e(Ξ²Β·G₁ + G₁', Gβ‚‚ + Ξ²Β·Gβ‚‚') = e(G₁, Gβ‚‚)^Ξ² Β· e(G₁, Gβ‚‚')^(Ξ²Β²) Β· e(G₁', Gβ‚‚) Β· e(G₁', Gβ‚‚')^Ξ² ``` If Ξ± β‰  Ξ², then e(u₁, v₁) β‰  e(uβ‚‚, vβ‚‚) (different Ξ±Β² vs Ξ²Β² terms in exponents). **[WI β†’ Equality]** WI CRS has perfectly orthogonal basis: `e(u₁, vβ‚‚) = e(uβ‚‚, v₁) = 1_T`. By bilinearity and GS basis algebra, this orthogonality constraint forces: ``` e(u₁, v₁) = e(uβ‚‚, vβ‚‚) = e(G₁, Gβ‚‚) Β· e(G₁', Gβ‚‚') (common value) ``` **[Biconditional]** The pairing check `e(u₁, v₁) β‰  e(uβ‚‚, vβ‚‚)` therefore distinguishes binding from WI with perfect accuracy: - No false positives: All binding CRS satisfy inequality - No false negatives: All WI CRS satisfy equality ∎ **Corollary 1.1:** Non-binding CRS enables commitment malleability (PVUGC-002 attack vector). **Reference:** Groth & Sahai, "Efficient Non-interactive Proof Systems" (EUROCRYPT 2008), Β§3.2 **Verification status:** βœ… M2's algorithm correctly implements this check (see Appendix A10.M101) --- ### Finding 2: M2's Canonical Algorithm is Complete and Correct **Algorithm analysis (ValidateCrsAndComputeDigest):** **Stage 1: Parsing (lines 43-51)** ```pseudocode TRY: (u1, u2, v1, v2) = ParseCRS(CRS_data) CATCH ParsingError: RETURN (status: "REJECT", reason: "Invalid CRS serialization") ``` **Security properties:** - βœ… Graceful error handling (no exceptions leak) - βœ… Structure validation before cryptographic checks - βœ… Prevents processing malformed data **Completeness:** Covers structural malformation (Test Case 3) --- **Stage 2: Subgroup and Identity Checks (lines 53-63)** ```pseudocode FOR p in points_to_check: IF NOT p.is_on_curve(): RETURN (status: "REJECT", reason: "Point not on curve") IF p.is_identity(): RETURN (status: "REJECT", reason: "CRS contains identity element") IF NOT p.is_in_correct_subgroup(): RETURN (status: "REJECT", reason: "Point not in prime-order subgroup") ``` **Security properties:** - βœ… Point-on-curve validation (prevents invalid point attacks) - βœ… Identity element rejection (prevents trivial CRS) - βœ… Subgroup membership (cofactor clearing for BLS12-381) - βœ… Executed before pairing operations (efficiency + security) **Critical security:** BLS12-381 elliptic curve cofactors: - **𝔾₁ (E(𝔽_p)):** prime-order subgroup of order r, cofactor **h₁ = 1** (no cofactor clearing needed) - **𝔾₂ (E'(𝔽_pΒ²)):** prime-order subgroup of order r, cofactor **hβ‚‚ β‰ˆ 2^128** (cofactor clearing REQUIRED) **Subgroup check implementation:** - For 𝔾₁: point-on-curve check suffices (h₁ = 1 implies no low-order points) - For 𝔾₂: MUST verify `[hβ‚‚]P ∈ 𝔾₂` (Bowe's method) or `[r]P = O` (scalar multiplication) **Security rationale:** Without 𝔾₂ cofactor clearing, attacker can supply low-order v₁, vβ‚‚ that pass point-on-curve but fail pairing checks unpredictably, enabling denial-of-service. **References:** - BLS12-381 For The Rest Of Us: https://hackmd.io/@benjaminion/bls12-381#Cofactors - Bowe's faster cofactor clearing: https://eprint.iacr.org/2019/814.pdf **Completeness:** Covers malformed points, identity, small-order (Test Case 3, extended Test Case 5) --- **Stage 3: Binding Property Check (lines 65-72)** ```pseudocode p1 = pairing(u1, v1) p2 = pairing(u2, v2) IF p1 == p2: RETURN (status: "REJECT", reason: "CRS is not binding (p1 == p2)") ``` **Security properties:** - βœ… Direct test of orthogonality condition - βœ… Constant-time comparison required (comment at line 70) - βœ… Clear rejection reason for debugging **Cost analysis:** - **2 pairing operations:** ~2-4ms each on modern hardware (BLS12-381) - **1 𝔾_T equality check:** ~10Β΅s (constant-time) - **Total:** ~5-10ms (acceptable for setup-time operation) **Constant-time requirement (line 70-71):** "Comparison MUST be constant-time if CRS data is ever considered secret." **Cryptographic justification:** While CRS is typically public, constant-time comparison prevents timing side-channels during validation that could leak information about CRS structure. Best practice: always use constant-time for cryptographic comparisons. **Completeness:** Covers non-binding CRS detection (Test Case 2) --- **Stage 4: Canonical Digest Computation (lines 74-77)** ```pseudocode serialized_crs = CanonicalSerialize(u1, u2, v1, v2, ...) digest = H_bytes("PVUGC/GS-CRS/v1" || serialized_crs || "BINDING_SXDH") ``` **Security properties:** - βœ… Domain separation: `"PVUGC/GS-CRS/v1"` prevents cross-protocol attacks - βœ… Canonical serialization: ensures deterministic digest across implementations - βœ… Binding tag: `"BINDING_SXDH"` included in preimage (not just metadata) - βœ… Collision resistance: SHA-256 provides 128-bit security **Digest structure:** ``` digest = SHA256("PVUGC/GS-CRS/v1" || compressed_point(u₁) || compressed_point(uβ‚‚) || compressed_point(v₁) || compressed_point(vβ‚‚) || "BINDING_SXDH") ``` **Canonical serialization requirements:** - Compressed point format (BLS12-381: 48 bytes for 𝔾₁, 96 bytes for 𝔾₂) - Fixed endianness (big-endian per BLS12-381 standard) - Y-coordinate sign bit (compressed encoding) - Reject non-canonical encodings (multiple representations) **Multi-CRS extension (Β§92):** ``` For AND-of-2 CRS: GS_instance_digest = SHA256("PVUGC/GS-MULTI/v1" || digest_CRS1 || digest_CRS2) ``` **Completeness:** Produces deterministic, verifiable digest (Test Case 1) --- **Stage 5: Return Success (lines 79-80)** ```pseudocode RETURN (status: "ACCEPT", digest: digest) ``` **Integration with protocol ([`PVUGC-2025-10-20.md Β§1 Introduction`](../PVUGC-2025-10-20)):** 1. Call `ValidateCrsAndComputeDigest(CRS_data, curve_params)` 2. If REJECT: abort setup, log reason 3. If ACCEPT: include `digest` in `GS_instance_digest` 4. `GS_instance_digest` β†’ `header_meta` (line 73) 5. `header_meta` β†’ `arming_pkg_hash` β†’ `ctx_hash` (lines 60-62) 6. `ctx_hash` β†’ KDF (line 91) **Security benefit:** CRS cryptographically bound to context. Substitution changes digest β†’ ctx_hash β†’ K β†’ decryption fails. --- ### Finding 3: Binding Verification Prevents Attack 10.1 (Non-Binding CRS Acceptance) **Attack scenario (v1.0 vulnerability):** ``` Setup: 1. Attacker generates WI CRS with orthogonal basis: u₁ = (Ξ±Β·G₁, G₁), uβ‚‚ = (Ξ²Β·G₁, G₁) v₁ = (Gβ‚‚, Ξ±Β·Gβ‚‚), vβ‚‚ = (Gβ‚‚, Ξ²Β·Gβ‚‚) where e(u₁, v₁) = e(uβ‚‚, vβ‚‚) = e(G₁, Gβ‚‚)^(Ξ±+1) 2. WI property: Commitments can be re-randomized to open to different values C = (c₁, cβ‚‚) with randomizer (r₁, rβ‚‚) Can find (r₁', rβ‚‚') such that C opens to different value 3. Attacker publishes GS attestation with WI CRS Attack: 4. Commitments in attestation are malleable 5. Attacker can create multiple valid openings 6. Could forge attestations without valid Groth16 proof 7. Breaks soundness (PVUGC-002) Impact: Complete protocol break (no-proof-spend violated) Computational Complexity: - CRS generation: O(1) group operations (compute u₁, uβ‚‚, v₁, vβ‚‚) - WI property verification: O(1) pairing operations (check orthogonality) - Total: O(1) cryptographic operations (feasible for attacker) - Success condition: ValidateCrsAndComputeDigest fails to detect WI property - Success probability (with v2.0): 0 (deterministic rejection per Theorem 2) ``` **v2.0 mitigation:** ``` ValidateCrsAndComputeDigest rejects WI CRS: 1. Compute p1 = e(u₁, v₁) = e(G₁, Gβ‚‚)^(Ξ±+1) 2. Compute p2 = e(uβ‚‚, vβ‚‚) = e(G₁, Gβ‚‚)^(Ξ²+1) 3. For WI CRS: p1 == p2 (both equal e(G₁, Gβ‚‚)^(Ξ±+1) by orthogonality) 4. Algorithm returns: (status: "REJECT", reason: "CRS is not binding (p1 == p2)") 5. Setup aborts, attacker cannot proceed ``` **Formal verification:** **Theorem 2 (WI CRS Rejection):** `ValidateCrsAndComputeDigest` rejects all witness-indistinguishable GS-CRS with probability 1. *Proof:* By contradiction. Assume WI CRS passes validation. - WI CRS has perfectly orthogonal basis (definition) - Orthogonality implies `e(u₁, v₁) = e(uβ‚‚, vβ‚‚)` - Algorithm line 71 checks `p1 == p2` - If equal, returns REJECT (line 72) - Contradiction: cannot pass validation ∎ **Status:** βœ… Attack 10.1 prevented by M2's algorithm --- ### Finding 4: CRS-Context Binding Prevents Attack 10.2 (CRS Substitution) **Attack scenario (v1.0 vulnerability):** ``` Setup: - Armers publish artifacts {D₁, Dβ‚‚, ct} for honest CRS₁ - v1.0 does not bind CRS to context cryptographically Attack: 1. Attacker observes arming artifacts for honest CRS₁ 2. Generates malicious CRSβ‚‚ with known trapdoor Ο„ 3. Publishes CRSβ‚‚ to decappers (substitution) 4. Decapper uses CRSβ‚‚ to compute KEM key 5. With trapdoor Ο„, attacker computes M without valid proof 6. Decrypts adaptor secret Ξ± 7. Completes signature without proving Impact: No-proof-spend property broken Computational Complexity: - CRSβ‚‚ generation with trapdoor: O(1) group operations - Substitution: O(1) (publish malicious CRS) - Decryption attempt: O(1) (KDF derivation with wrong digest) - Total: O(1) protocol operations - Success condition: K_i(CRSβ‚‚) = K_i(CRS₁) - Success probability (with v2.0): ≀ 2^(-128) (collision attack per Theorem 3) ``` **v2.0 mitigation:** **Digest chain (PVUGC-2025-10-20.md Β§1 Introduction lines 60-62, 73, 91):** ``` digest_CRS1 = ValidateCrsAndComputeDigest(CRS₁, curve_params).digest GS_instance_digest = digest_CRS1 (or multi-CRS extension) header_meta = H("..." || GS_instance_digest || ...) [line 73] arming_pkg_hash = H("PVUGC/ARM" || {D1} || {D2} || header_meta) [line 60] ctx_hash = H("PVUGC/CTX" || ctx_core || arming_pkg_hash || presig_pkg_hash) [line 62] K_i = Poseidon2(ser(M_i) || H_bytes(ctx_hash) || GS_instance_digest) [line 91] ``` **Security observation (Defense-in-Depth):** GS_instance_digest binds CRS to protocol execution at TWO layers: 1. **Context layer:** GS_instance_digest β†’ header_meta β†’ arming_pkg_hash β†’ ctx_hash - Effect: Different CRS changes ctx_hash, affecting ALL context-dependent derivations 2. **KDF layer:** GS_instance_digest appears DIRECTLY in Poseidon2 input (line 91) - Effect: Different CRS changes K_i EVEN IF attacker somehow forged ctx_hash collision **Implication:** CRS substitution attack must break collision resistance at BOTH layers: - Pr[success] ≀ min(Ξ΅_SHA256, Ξ΅_Poseidon2) - With both ≀ 2^(-128), combined security is β‰₯ 2^(-128) This dual binding is defense-in-depth: neither layer alone is sufficient for security, but together they provide redundant protection against implementation errors or future cryptanalysis. **Substitution attack failure:** ``` Honest execution (CRS₁): 1. Armer computes digest_CRS1, includes in GS_instance_digest 2. Publishes header_meta with digest_CRS1 3. ctx_hash computed with digest_CRS1 4. K_i = KDF(M_i || ctx_hash_CRS1 || digest_CRS1) 5. ct_i = (s_i || h_i) βŠ• keystream(K_i) Attacker substitution attempt (CRSβ‚‚): 6. Attacker publishes CRSβ‚‚ to decapper 7. Decapper computes digest_CRS2 (different from digest_CRS1) 8. Recomputes ctx_hash' with digest_CRS2 9. K_i' = KDF(M_i || ctx_hash_CRS2 || digest_CRS2) 10. K_i' β‰  K_i (different ctx_hash and digest) 11. Decryption fails: (s_i || h_i) βŠ• keystream(K_i') β‰  (s_i || h_i) 12. Cannot recover Ξ± ``` **Security reduction:** **Theorem 3 (CRS Binding):** Under collision resistance of SHA-256 and Poseidon2, an attacker cannot substitute CRS after arming without detection (decryption failure) except with negligible probability. *Proof:* - Assume attacker finds CRS₁ β‰  CRSβ‚‚ such that decryption succeeds - Decryption success requires K_i computed with CRSβ‚‚ equals K_i computed with CRS₁ - K_i = Poseidon2(M_i || ctx_hash || GS_instance_digest) - ctx_hash includes header_meta which includes GS_instance_digest - GS_instance_digest = digest_CRS (from ValidateCrsAndComputeDigest) - CRS₁ β‰  CRSβ‚‚ implies digest_CRS1 β‰  digest_CRS2 (collision resistance of SHA-256) - digest_CRS1 β‰  digest_CRS2 implies ctx_hash_CRS1 β‰  ctx_hash_CRS2 (collision resistance) - Different ctx_hash implies different K_i (collision resistance of Poseidon2) - Contradiction: K_i computed with CRSβ‚‚ cannot equal K_i computed with CRS₁ ∎ **Probability bound:** Collision probability ≀ 2^(-128) (SHA-256 birthday bound) **Status:** βœ… Attack 10.2 prevented by digest chain --- ### Finding 5: Multi-CRS Defense Provides Defense-in-Depth **Single CRS risk (v1.0):** ``` Scenario: CRS ceremony compromised - Single participant knows trapdoor Ο„ - Can create fake attestations - Breaks soundness completely - Single point of failure ``` **Multi-CRS AND-ing (v2.0, Β§92):** ``` MUST: Minimum 2 independent binding GS-CRS transcripts - CRS₁ from ceremony A (participants {P1, P2, P3}) - CRSβ‚‚ from ceremony B (participants {Q1, Q2, Q3}) - Different venues, different randomness sources - Both digests in GS_instance_digest Verification: Logical AND of both PPE checks - Must satisfy GS verification for CRS₁ AND CRSβ‚‚ - M_i^{AND} = ser(M_i^(1)) || ser(M_i^(2)) ``` **Security amplification:** **Theorem 4 (Multi-CRS Security):** If at least one CRS is honest (no trapdoor known), the protocol remains sound. *Proof:* - Attacker must create valid GS attestations for both CRS₁ and CRSβ‚‚ - Honest CRS has binding property (commitments extractable) - GS soundness: valid attestation implies valid Groth16 proof - Attacker cannot forge attestation for honest CRS without proof - Therefore: multi-CRS requires valid proof ∎ **Ceremony compromise resistance:** ``` Single CRS (v1.0): - Break 1 ceremony β†’ protocol broken - Probability: P(compromise₁) Multi-CRS (v2.0): - Break ALL ceremonies β†’ protocol broken - Probability: P(compromise₁) Γ— P(compromiseβ‚‚) - Example: If P = 0.01 per ceremony β†’ 0.0001 for both - 100x improvement ``` **Best practice (Β§92):** Independent ceremonies with: - Different participants (no overlap) - Different venues (geographic separation) - Different randomness sources (NIST beacon, dice rolls, etc.) - Public audit trails (transcripts, recordings) **Status:** βœ… Defense-in-depth validated --- ### Finding 6: Test Vector Expansion Required **M2 provided 3 test cases (see Appendix A10.M101):** - Test Case 1: Valid binding CRS β†’ ACCEPT - Test Case 2: Invalid non-binding (WI) CRS β†’ REJECT "CRS is not binding" - Test Case 3: Malformed CRS β†’ REJECT "Point not on curve" or "Invalid serialization" **Gap:** Insufficient coverage for all algorithm paths **Required test vector expansion:** **Category 1: Structural Validation (3 vectors)** **Test Vector 1.1: Valid Binding CRS (BLS12-381, SXDH)** ``` Input: curve: BLS12-381 CRS_data: [compressed point hex] u₁ = 0x... (48 bytes, 𝔾₁) uβ‚‚ = 0x... (48 bytes, 𝔾₁) v₁ = 0x... (96 bytes, 𝔾₂) vβ‚‚ = 0x... (96 bytes, 𝔾₂) Expected Output: status: "ACCEPT" digest: 0xabc123... (32 bytes, SHA-256) Verification: - All points on curve: βœ“ - Subgroup membership: βœ“ - Binding check: e(u₁, v₁) β‰  e(uβ‚‚, vβ‚‚) βœ“ - Digest recomputation matches: βœ“ ``` **Test Vector 1.2: Malformed CRS (Invalid Point Encoding)** ``` Input: curve: BLS12-381 CRS_data: 0xdeadbeef... (invalid point data) Expected Output: status: "REJECT" reason: "Invalid CRS serialization" or "Point not on curve" Verification: - Parsing fails or point validation fails - Algorithm returns early (line 51 or 58) ``` **Test Vector 1.3: CRS with Wrong Curve** ``` Input: curve: BLS12-381 CRS_data: [valid BN254 CRS] Expected Output: status: "REJECT" reason: "Point not on curve" Verification: - Points from BN254 curve don't lie on BLS12-381 - is_on_curve() returns false (line 57) ``` --- **Category 2: Identity and Small-Order Points (2 vectors)** **Test Vector 2.1: CRS with Identity Element** ``` Input: curve: BLS12-381 CRS_data: u₁ = point_at_infinity, uβ‚‚/v₁/vβ‚‚ valid Expected Output: status: "REJECT" reason: "CRS contains identity element" Verification: - Identity check detects point at infinity (line 59) - Prevents trivial CRS ``` **Test Vector 2.2: CRS with Small-Order Point** ``` Input: curve: BLS12-381 CRS_data: v₁ in small-order subgroup (not prime-order, 𝔾₂ cofactor) Expected Output: status: "REJECT" reason: "Point not in prime-order subgroup" Verification: - Subgroup check via cofactor clearing (line 62) - BLS12-381: h₁ = 1 (𝔾₁), hβ‚‚ β‰ˆ 2^128 (𝔾₂ requires cofactor clearing) - If point has order dividing cofactor: reject ``` --- **Category 3: Binding Property (2 vectors)** **Test Vector 3.1: Non-Binding (WI) CRS** ``` Input: curve: BLS12-381 CRS_data: [structurally valid WI CRS] Orthogonal basis: e(u₁, v₁) = e(uβ‚‚, vβ‚‚) Expected Output: status: "REJECT" reason: "CRS is not binding (p1 == p2)" Verification: - Structural checks pass - Pairing equality detected (line 71) - Confirms binding detection works ``` **Test Vector 3.2: Binding CRS (Alternative Parameters)** ``` Input: curve: BLS12-381 CRS_data: [different valid binding CRS] Different Ξ±, Ξ² parameters Expected Output: status: "ACCEPT" digest: 0xdef456... (different from Test Vector 1.1) Verification: - Confirms binding check for different parameters - Digest changes with different CRS ``` --- **Category 4: Digest Computation (2 vectors)** **Test Vector 4.1: Canonical Serialization (Big-Endian)** ``` Input: curve: BLS12-381 CRS_data: [valid binding CRS with known serialization] Expected Output: digest: 0x[predetermined value] Verification: - Confirms canonical serialization (big-endian) - Cross-implementation compatibility - Bit-exact digest match ``` **Test Vector 4.2: Multi-CRS Digest** ``` Input: curve: BLS12-381 CRS1_data: [valid binding CRS] CRS2_data: [valid binding CRS, independent] Expected Output: digest_CRS1: 0x... digest_CRS2: 0x... GS_instance_digest: SHA256("PVUGC/GS-MULTI/v1" || digest_CRS1 || digest_CRS2) Verification: - Both CRS validated independently - Combined digest computation (Β§92) ``` --- **Category 5: Edge Cases (2 vectors)** **Test Vector 5.1: Non-Canonical Encoding** ``` Input: curve: BLS12-381 CRS_data: [point with non-canonical encoding] (e.g., uncompressed format when compressed required) Expected Output: status: "REJECT" reason: "Invalid CRS serialization" (non-canonical) Verification: - Rejects redundant encodings - Enforces compressed format ``` **Test Vector 5.2: Constant-Time Comparison Verification** ``` Input: curve: BLS12-381 CRS_data: [valid binding CRS] Side-Channel Test: - Measure timing of pairing equality check (line 71) - Compare with WI CRS timing Expected: - Timing variance < 1% (constant-time) - No correlation between CRS structure and timing Verification: - Confirms constant-time implementation (line 70-71 requirement) ``` **Total test vectors:** 11 comprehensive cases covering all algorithm paths --- ### Finding 7: Implementation Guidance and Tooling Needed **Gap:** While algorithm is complete, practical implementation guidance missing **Required artifacts:** #### 7.1 Reference Implementation **Canonical implementation in Rust (example):** ```rust // Cargo.toml dependencies (minimum versions): // [dependencies] // bls12_381 = "0.8.0" # First version with is_torsion_free() for G2 // subtle = "2.5.0" # Stable ConstantTimeEq trait // sha2 = "0.10.0" # Modern SHA-256 implementation use bls12_381::{G1Affine, G2Affine, pairing, Gt}; use sha2::{Sha256, Digest}; use subtle::ConstantTimeEq; pub struct CrsValidationResult { pub status: Status, pub digest: Option<[u8; 32]>, pub reason: Option, } pub enum Status { Accept, Reject, } pub fn validate_crs_and_compute_digest( crs_data: &[u8], ) -> CrsValidationResult { // Stage 1: Parse let (u1, u2, v1, v2) = match parse_crs(crs_data) { Ok(crs) => crs, Err(e) => return CrsValidationResult { status: Status::Reject, digest: None, reason: Some(format!("Invalid CRS serialization: {}", e)), }, }; // Stage 2: Subgroup checks let points_g1 = [u1, u2]; let points_g2 = [v1, v2]; for p in &points_g1 { if p.is_identity().into() { return CrsValidationResult { status: Status::Reject, digest: None, reason: Some("CRS contains identity element".to_string()), }; } if !p.is_on_curve().into() { return CrsValidationResult { status: Status::Reject, digest: None, reason: Some("Point not on curve".to_string()), }; } // Subgroup check (BLS12-381 G1 is already prime-order after is_on_curve) if !p.is_torsion_free().into() { return CrsValidationResult { status: Status::Reject, digest: None, reason: Some("Point not in prime-order subgroup".to_string()), }; } } // G2 checks (with hβ‚‚ cofactor clearing) for p in &points_g2 { if p.is_identity().into() { return CrsValidationResult { status: Status::Reject, digest: None, reason: Some("CRS contains identity element".to_string()), }; } if !p.is_on_curve().into() { return CrsValidationResult { status: Status::Reject, digest: None, reason: Some("Point not on curve".to_string()), }; } // CRITICAL: G2 subgroup check (hβ‚‚ β‰ˆ 2^128, cofactor clearing required) if !p.is_torsion_free().into() { return CrsValidationResult { status: Status::Reject, digest: None, reason: Some("Point not in prime-order subgroup".to_string()), }; } } // Stage 3: Binding check let p1 = pairing(&u1, &v1); let p2 = pairing(&u2, &v2); // Constant-time comparison if ct_eq(&p1, &p2) { return CrsValidationResult { status: Status::Reject, digest: None, reason: Some("CRS is not binding (p1 == p2)".to_string()), }; } // Stage 4: Digest computation let digest = compute_crs_digest(&u1, &u2, &v1, &v2); // Stage 5: Success CrsValidationResult { status: Status::Accept, digest: Some(digest), reason: None, } } fn compute_crs_digest( u1: &G1Affine, u2: &G1Affine, v1: &G2Affine, v2: &G2Affine, ) -> [u8; 32] { let mut hasher = Sha256::new(); hasher.update(b"PVUGC/GS-CRS/v1"); hasher.update(u1.to_compressed()); hasher.update(u2.to_compressed()); hasher.update(v1.to_compressed()); hasher.update(v2.to_compressed()); hasher.update(b"BINDING_SXDH"); hasher.finalize().into() } // Constant-time Gt equality (requires careful implementation) fn ct_eq(a: &Gt, b: &Gt) -> bool { use subtle::ConstantTimeEq; let a_bytes = a.to_bytes(); let b_bytes = b.to_bytes(); a_bytes.ct_eq(&b_bytes).into() } ``` **Requirements:** - βœ… Follows M2's algorithm structure exactly - βœ… Constant-time comparison (subtle crate) - βœ… Canonical serialization (compressed points) - βœ… Error handling (Result types) - βœ… BLS12-381 library (bls12_381 crate >= 0.8.0) - βœ… G2 cofactor clearing (is_torsion_free for hβ‚‚ β‰ˆ 2^128) --- #### 7.2 CRS Generation Ceremony Best Practices **MPC Ceremony Structure:** **Phase 1: Setup (Pre-Ceremony)** ``` Organizer: 1. Announce ceremony parameters: - Curve: BLS12-381 - CRS type: SXDH binding - Minimum participants: 3 (recommend 5-10) - Ceremony date/time - Communication protocol (secure channels) 2. Participant recruitment: - Public call for participation - Diverse backgrounds (academic, industry, independent) - Geographic distribution - No financial dependencies 3. Tooling setup: - Reference ceremony software - Transcript format specification - Verification tools ``` **Phase 2: Ceremony Execution** ``` Round 1: Participant 1 1. Sample random α₁ ← β„€α΅£* 2. Compute CRS₁ = Setup(α₁) 3. Publish CRS₁, commitment to α₁ 4. Destroy α₁ (secure deletion) Round i: Participant i 1. Receive CRS_{i-1} 2. Sample random Ξ±α΅’ ← β„€α΅£* 3. Update CRS: CRSα΅’ = Update(CRS_{i-1}, Ξ±α΅’) 4. Publish CRSα΅’, proof of correct update 5. Destroy Ξ±α΅’ Final Round: Participant n 1. Receive CRS_{n-1} 2. Update to CRS_final 3. Compute digest_CRS = ValidateCrsAndComputeDigest(CRS_final).digest 4. Publish CRS_final, digest_CRS, full transcript ``` **Phase 3: Post-Ceremony Verification** ``` Public verification: 1. Anyone can download transcript 2. Verify each round: - Correct update from CRS_{i-1} to CRSα΅’ - Proof of knowledge of Ξ±α΅’ 3. Verify final CRS: - Run ValidateCrsAndComputeDigest(CRS_final) - Check: status = "ACCEPT" - Check: digest matches published digest_CRS 4. Verify binding property independently Acceptance criteria: - All rounds verified βœ“ - Final CRS passes binding check βœ“ - At least 1 honest participant (threshold assumption) ``` **Randomness Sources (Best Practices):** ``` Primary sources: 1. Hardware RNG (Intel RDRAND, ARM TrustZone) 2. /dev/urandom on audited Linux system 3. NIST randomness beacon (public verifiability) 4. Physical entropy (dice rolls, coin flips, recorded and published) Combination: Ξ±_i = H(RDRAND() || urandom() || NIST_beacon() || dice_rolls()) Documentation: - Record all sources used - Publish raw entropy samples - Include in ceremony transcript ``` **Security Considerations:** ``` Threat model: - Compromised participant: OK if at least 1 honest - Network attack: Use authenticated channels (Signal, PGP) - Coordinator compromise: Ceremony verifiable by anyone post-hoc - Randomness failure: Combine multiple independent sources Required: - Live streaming or recording (transparency) - Public transcript (JSON format, signed) - Independent verification tools - Post-ceremony security audit ``` --- #### 7.3 Binding Verification Tool **Command-Line Tool Specification:** **Tool: `pvugc-verify-crs`** **Usage:** ```bash # Basic verification $ pvugc-verify-crs --crs crs.json # With ceremony transcript $ pvugc-verify-crs --crs crs.json --transcript ceremony.json # Multi-CRS verification $ pvugc-verify-crs --crs crs1.json --crs crs2.json --multi # Output digest for inclusion in GS_instance_digest $ pvugc-verify-crs --crs crs.json --output-digest ``` **Output Format:** ``` PVUGC CRS Verification Tool v1.0 ================================= CRS File: crs.json Curve: BLS12-381 CRS Type: SXDH Binding [1/5] Parsing CRS structure... βœ“ u₁: 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb uβ‚‚: 0x08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 v₁: 0x0606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be vβ‚‚: 0x0cef41c7c2c4ee7e2db7a3f8c1f4d5c4e8c1b0e5d8c2f9a6b3e7d4c8a9f1e2d5c6b [2/5] Subgroup membership checks... βœ“ All points on curve: βœ“ No identity elements: βœ“ Prime-order subgroup (G1 h₁=1, G2 hβ‚‚β‰ˆ2^128): βœ“ [3/5] Binding property verification... βœ“ Computing e(u₁, v₁)... [2.3ms] Computing e(uβ‚‚, vβ‚‚)... [2.4ms] Comparing (constant-time)... βœ“ Result: e(u₁, v₁) β‰  e(uβ‚‚, vβ‚‚) [BINDING] [4/5] Digest computation... βœ“ Canonical serialization: 288 bytes Domain separation: "PVUGC/GS-CRS/v1" SHA-256 digest: 0xabc123def456789... [5/5] Cross-verification with ceremony transcript... βœ“ Transcript digest matches: βœ“ Ceremony round count: 7 participants Public verification: 142 independent verifications recorded ===================================== VERIFICATION RESULT: βœ… BINDING CRS ===================================== Digest for GS_instance_digest: 0xabc123def456789abcdef0123456789abcdef0123456789abcdef0123456789 Security Level: 128-bit (BLS12-381) Ceremony Date: 2025-10-01 Participants: 7 (threshold: 1 honest required) Recommended action: ACCEPT this CRS for use in PVUGC protocol ``` **Features:** - βœ… Parse CRS from JSON, binary, or hex formats - βœ… Verify all 5 stages of ValidateCrsAndComputeDigest - βœ… Timing measurements (detect non-constant-time) - βœ… Cross-check with ceremony transcript - βœ… Output digest for protocol integration - βœ… Multi-CRS support (AND-of-2 verification) - βœ… Human-readable and machine-parseable output (JSON mode) --- #### 7.4 CRS Ceremony Audit Trail Requirements **Specification: Ceremony Transcript Format (JSON)** ```json { "ceremony_metadata": { "version": "PVUGC-CRS-CEREMONY/v1", "curve": "BLS12-381", "crs_type": "SXDH_BINDING", "ceremony_id": "PVUGC-CRS-2025-10-01-A", "start_time": "2025-10-01T12:00:00Z", "end_time": "2025-10-01T18:30:00Z", "coordinator": "Alice (coordinator@example.com)", "participants": [ { "id": "P1", "name": "Bob", "contact": "bob@example.com", "pgp_fingerprint": "ABCD1234...", "location": "New York, USA" }, { "id": "P2", "name": "Carol", "contact": "carol@example.com", "pgp_fingerprint": "EFGH5678...", "location": "London, UK" } ], "minimum_honest_threshold": 1, "security_assumptions": "At least 1 honest participant" }, "ceremony_rounds": [ { "round": 1, "participant_id": "P1", "timestamp": "2025-10-01T12:15:00Z", "randomness_sources": [ { "type": "hardware_rng", "details": "Intel RDRAND", "entropy_sample": "0x..." }, { "type": "nist_beacon", "pulse_id": "123456", "output_value": "0x..." }, { "type": "physical_dice", "video_url": "https://ceremony.example.com/videos/p1_dice.mp4", "dice_rolls": [3, 5, 2, 6, 1, 4] } ], "crs_input": null, "crs_output": { "u1": "0x...", "u2": "0x...", "v1": "0x...", "v2": "0x..." }, "proof_of_knowledge": { "type": "Schnorr_PoK", "proof": "0x..." }, "commitment": "0x...", "signature": { "type": "PGP", "signature": "-----BEGIN PGP SIGNATURE-----\n..." } }, { "round": 2, "participant_id": "P2", "timestamp": "2025-10-01T13:00:00Z", "randomness_sources": [ /* ... */ ], "crs_input": { "round": 1, "crs_digest": "0x..." }, "crs_output": { /* ... */ }, "update_proof": "0x...", "commitment": "0x...", "signature": { /* ... */ } } ], "final_crs": { "crs_data": { "u1": "0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb", "u2": "0x08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1", "v1": "0x0606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be", "v2": "0x0cef41c7c2c4ee7e2db7a3f8c1f4d5c4e8c1b0e5d8c2f9a6b3e7d4c8a9f1e2d5c6b" }, "binding_verification": { "pairing_1": "0x...", "pairing_2": "0x...", "is_binding": true, "verification_timestamp": "2025-10-01T18:30:00Z" }, "digest": "0xabc123def456789abcdef0123456789abcdef0123456789abcdef0123456789", "digest_algorithm": "SHA-256", "domain_separation": "PVUGC/GS-CRS/v1 || crs_data || BINDING_SXDH" }, "independent_verifications": [ { "verifier": "Dave (dave@example.com)", "timestamp": "2025-10-01T19:00:00Z", "verification_tool": "pvugc-verify-crs v1.0", "result": "ACCEPT", "digest_match": true, "signature": "-----BEGIN PGP SIGNATURE-----\n..." }, { "verifier": "Eve (eve@example.com)", "timestamp": "2025-10-01T20:15:00Z", "verification_tool": "custom_verifier v0.1", "result": "ACCEPT", "digest_match": true, "signature": "-----BEGIN PGP SIGNATURE-----\n..." } ], "audit_trail": { "video_recording_url": "https://ceremony.example.com/videos/full_ceremony.mp4", "live_stream_archive_url": "https://youtube.com/watch?v=...", "chat_transcript_url": "https://ceremony.example.com/transcripts/chat.txt", "security_audit_report_url": "https://ceremony.example.com/audit_report.pdf" } } ``` **Requirements:** - βœ… Complete round-by-round execution log - βœ… Randomness source documentation (verifiable) - βœ… Cryptographic commitments and proofs - βœ… PGP signatures from all participants - βœ… Final CRS with binding verification result - βœ… Independent verification records - βœ… Multimedia audit trail (video, chat logs) **Publication:** - Upload to public archive (IPFS, Arweave, GitHub) - Provide SHA-256 digest of transcript - Include in protocol documentation - Enable community verification --- ## Recommendations ### Normative (MUST) **R1: Add Canonical Algorithm to Specification** **Priority:** P0 | **Timeline:** Immediate Add M2's `ValidateCrsAndComputeDigest` algorithm (see Appendix A10.M101) as a new normative section in PVUGC-2025-10-20.md Β§1 Introduction: **Proposed location:** After Β§91 (Production Profile) **Proposed section:** Β§92 "CRS Validation Algorithm (Normative)" **Content:** ```markdown ### 92) CRS Validation Algorithm (Normative) Implementations MUST validate GS-CRS using the following canonical algorithm before including the CRS digest in `GS_instance_digest`. **Algorithm**: `ValidateCrsAndComputeDigest` **Input:** - `CRS_data`: Byte-string representation of GS-CRS - `curve_params`: BLS12-381 curve parameters **Output:** - On success: `(status: "ACCEPT", digest: <32-byte SHA-256 digest>)` - On failure: `(status: "REJECT", reason: )` **Procedure:** 1. **Parse and Structurally Validate** - Deserialize `CRS_data` to extract `(u₁, uβ‚‚, v₁, vβ‚‚)` - If parsing fails: RETURN `(status: "REJECT", reason: "Invalid CRS serialization")` 2. **Subgroup and Identity Checks** - For each point in `{u₁, uβ‚‚}` (𝔾₁): - Verify point is on curve (BLS12-381) - Verify point is not identity element - Verify point is torsion-free (h₁ = 1, automatic after on-curve check) - For each point in `{v₁, vβ‚‚}` (𝔾₂): - Verify point is on curve (BLS12-381) - Verify point is not identity element - Verify point is in prime-order subgroup (cofactor hβ‚‚ β‰ˆ 2^128, MUST clear cofactor) - If any check fails: RETURN `(status: "REJECT", reason: )` 3. **Binding Property Check** - Compute `p₁ = e(u₁, v₁)` (pairing operation) - Compute `pβ‚‚ = e(uβ‚‚, vβ‚‚)` (pairing operation) - Compare `p₁` and `pβ‚‚` using constant-time equality - If `p₁ == pβ‚‚`: RETURN `(status: "REJECT", reason: "CRS is not binding (p1 == p2)")` 4. **Canonical Digest Computation** - Serialize CRS in canonical form: - Compressed point encoding (BLS12-381 standard) - Big-endian byte order - Fixed-length: u₁, uβ‚‚ (48 bytes each), v₁, vβ‚‚ (96 bytes each) - Compute: `digest = SHA256("PVUGC/GS-CRS/v1" || ser(u₁) || ser(uβ‚‚) || ser(v₁) || ser(vβ‚‚) || "BINDING_SXDH")` 5. **Return Success** - RETURN `(status: "ACCEPT", digest: digest)` **Multi-CRS Extension (Β§89 requirement):** - For multi-CRS setup with n β‰₯ 2 CRS: - Validate each CRS independently using above algorithm - Compute: `GS_instance_digest = SHA256("PVUGC/GS-MULTI/v1" || digest_CRS1 || digest_CRS2 || ... || digest_CRSn)` **Implementation Requirements:** - MUST use constant-time comparison for pairing equality (step 3) - MUST reject non-canonical point encodings - MUST use canonical serialization (compressed, big-endian) - MUST include domain separation tags ("PVUGC/GS-CRS/v1", "BINDING_SXDH") - MUST perform G2 cofactor clearing (hβ‚‚ β‰ˆ 2^128) ``` **Acceptance criteria:** - [ ] Algorithm added to specification Β§92 - [ ] Marked as MUST (normative requirement) - [ ] Pseudocode matches M2's algorithm structure - [ ] Cross-referenced from Β§89-91 (binding CRS requirement) - [ ] G2 cofactor clearing requirement explicit --- **R2: Require Binding Check Before Digest Computation** **Priority:** P0 | **Timeline:** Immediate **Current spec (line 210):** "Runtime MUST reject non-binding CRS via a tag embedded in `GS_instance_digest`" **Enhancement:** Make explicit that binding check MUST precede digest computation **Proposed normative text (add to Β§92):** ```markdown **Binding Check Requirement (MUST):** Implementations MUST perform the binding property check (pairing comparison `e(u₁, v₁) β‰  e(uβ‚‚, vβ‚‚)`) BEFORE computing the CRS digest. The digest MUST NOT be computed or included in `GS_instance_digest` if the CRS fails the binding check. **Security rationale:** Computing and publishing a digest for a non-binding CRS could enable attackers to claim the CRS is validated when it is not. The binding check is the definitive test; the digest is a subsequent identifier for an already-validated CRS. ``` **Acceptance criteria:** - [ ] Normative text added - [ ] Cross-referenced in implementation guidelines - [ ] Test vectors verify rejection before digest computation (Test Vector 3.1) --- **R3: Mandate Constant-Time Pairing Equality Comparison** **Priority:** P0 | **Timeline:** Immediate **Rationale:** M2's algorithm (line 70-71) notes "comparison MUST be constant-time if CRS data is ever considered secret." Best practice: always use constant-time for cryptographic comparisons to prevent timing side-channels. **Proposed normative text (add to Β§92, step 3):** ```markdown **Constant-Time Comparison (MUST):** The pairing equality comparison in step 3 MUST be implemented using a constant-time comparison function. Variable-time comparisons (e.g., `memcmp`, `==` operator on byte arrays) are FORBIDDEN as they may leak information about CRS structure through timing side-channels. **Implementation guidance:** - Use constant-time comparison libraries (e.g., `subtle::ConstantTimeEq` in Rust, `crypto_verify_*` in libsodium) - Serialize 𝔾_T elements to fixed-length byte arrays - Compare byte-by-byte with constant-time logic - Verify constant-time property with side-channel tests (Test Vector 5.2) **Rationale:** While CRS is typically public, constant-time comparison is a defense-in-depth measure that prevents inadvertent information leakage during validation. ``` **Acceptance criteria:** - [ ] Constant-time requirement added to Β§92 - [ ] Implementation guidance provided - [ ] Test vector 5.2 (side-channel test) included --- **R4: Specify Minimum 2 Independent CRS Ceremonies** **Priority:** P1 | **Timeline:** Before production deployment **Current spec (Β§89, line 92):** "Multi-CRS AND-ing: use at least two independently generated binding GS-CRS transcripts" **Enhancement:** Add ceremony independence requirements **Proposed normative text (add to Β§93 "CRS Ceremony Requirements"):** ```markdown ### 93) CRS Ceremony Requirements (MUST/SHOULD) **Multi-CRS Requirement (MUST):** Production deployments MUST use at least 2 independent binding GS-CRS ceremonies. Each CRS MUST be validated using the algorithm in Β§92 before inclusion in `GS_instance_digest`. **Independence Criteria (MUST):** For ceremonies to be considered independent, they MUST satisfy: 1. **Participant Independence:** No overlap in ceremony participants 2. **Temporal Separation:** Ceremonies conducted on different dates (minimum 24 hours apart) 3. **Geographic Diversity:** Ceremonies in different jurisdictions (recommended: different continents) 4. **Randomness Independence:** No shared randomness sources between ceremonies 5. **Organizational Independence:** Different coordinators with no organizational ties **Security Goal:** An adversary must compromise ALL ceremonies to break protocol soundness. Independence requirements ensure this requires multiple independent breaches. **Ceremony Best Practices (SHOULD):** - Minimum 3 participants per ceremony (recommend 5-10) - Public announcement at least 14 days before ceremony - Live streaming or video recording (public transparency) - Multiple independent randomness sources (hardware RNG + NIST beacon + physical entropy) - Published transcript with verifiable commitments - Post-ceremony independent verification period (minimum 7 days) - Security audit by external cryptographer **Transcript Publication (MUST):** Ceremony coordinators MUST publish a complete transcript including: - Participant list with contact information - Round-by-round execution log - Randomness source documentation - Cryptographic commitments and proofs - Final CRS with binding verification result - SHA-256 digest of transcript - Public archive URL (IPFS, GitHub, or equivalent) ``` **Acceptance criteria:** - [ ] Section Β§93 added to specification - [ ] Independence criteria specified (5 requirements) - [ ] Best practices documented - [ ] Transcript format specified (JSON schema) --- ### Implementation/Testing **R5: Publish Reference Test Vector Suite** **Priority:** P1 | **Timeline:** 2 weeks **Deliverable:** Complete test vector suite (11 vectors, see Finding 6) **Format:** JSON test vectors file with template and generator ```json { "test_suite_version": "PVUGC-CRS-TEST/v1", "curve": "BLS12-381", "test_vectors": [ { "id": "1.1", "category": "structural_validation", "name": "valid_binding_crs_sxdh", "description": "Valid binding CRS with SXDH structure", "input": { "crs_data": "0x...", "u1": "0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb", "u2": "0x...", "v1": "0x...", "v2": "0x..." }, "expected_output": { "status": "ACCEPT", "digest": "0xabc123def456789abcdef0123456789abcdef0123456789abcdef0123456789", "reason": null }, "verification_steps": { "parsing": "success", "on_curve": true, "not_identity": true, "subgroup_check": true, "binding_check": "e(u1,v1) != e(u2,v2)", "digest_match": true } } // ... 10 more test vectors ] } ``` **Additional Deliverables:** 1. **Test Vector Template** (`crs_test_vector_template.json`): - JSON schema with field descriptions - Example values with inline comments - Validation script to check schema compliance 2. **Test Vector Generator** (`scripts/generate_crs_test_vectors.py`): - Programmatically generates CRS for all 11 test cases - Uses reference implementation for digest computation - Ensures bit-exact reproducibility **Test coverage:** - [ ] Category 1: Structural validation (3 vectors) - [ ] Category 2: Identity and small-order (2 vectors) - [ ] Category 3: Binding property (2 vectors) - [ ] Category 4: Digest computation (2 vectors) - [ ] Category 5: Edge cases (2 vectors) **Publication:** - Upload to GitHub repository: `pvugc/test-vectors/crs_validation.json` - Include in specification as normative reference - Provide verification script: `scripts/verify_crs_test_vectors.py` --- **R6: Develop Reference Implementation** **Priority:** P1 | **Timeline:** 4 weeks **Deliverable:** Reference implementation in Rust (see Finding 7.1) **Features:** - [ ] Complete ValidateCrsAndComputeDigest implementation - [ ] BLS12-381 curve (bls12_381 crate >= 0.8.0) - [ ] Constant-time comparison (subtle crate >= 2.5.0) - [ ] Canonical serialization (compressed points, big-endian) - [ ] Error handling (Result types with descriptive errors) - [ ] G2 cofactor clearing (is_torsion_free for hβ‚‚ β‰ˆ 2^128) - [ ] Test suite integration (runs all 11 test vectors) - [ ] Fuzzing harness (libfuzzer) - [ ] Documentation (rustdoc comments) - [ ] CI/CD pipeline (GitHub Actions) **Repository structure:** ``` pvugc-crs/ β”œβ”€β”€ src/ β”‚ β”œβ”€β”€ lib.rs (public API) β”‚ β”œβ”€β”€ validation.rs (ValidateCrsAndComputeDigest) β”‚ β”œβ”€β”€ parsing.rs (CRS deserialization) β”‚ β”œβ”€β”€ digest.rs (canonical digest computation) β”‚ └── constants.rs (domain separation tags) β”œβ”€β”€ tests/ β”‚ β”œβ”€β”€ test_vectors.rs (11 test vectors) β”‚ β”œβ”€β”€ integration.rs (end-to-end tests) β”‚ └── side_channel.rs (constant-time verification) β”œβ”€β”€ benches/ β”‚ └── validation.rs (performance benchmarks) β”œβ”€β”€ fuzz/ β”‚ └── fuzz_validation.rs (fuzzing targets) β”œβ”€β”€ examples/ β”‚ β”œβ”€β”€ validate_crs.rs (command-line tool) β”‚ └── ceremony_tool.rs (ceremony helper) └── README.md ``` **Acceptance criteria:** - [ ] Implementation passes all 11 test vectors - [ ] Fuzzing runs 1M+ iterations without crashes - [ ] Constant-time verification passes (valgrind, dudect) - [ ] Performance: validation < 10ms on modern hardware - [ ] External security review completed - [ ] Published on crates.io --- **R7: Create CRS Binding Verification Tool** **Priority:** P2 | **Timeline:** 4 weeks **Deliverable:** `pvugc-verify-crs` command-line tool (see Finding 7.3) **Features:** - [ ] Parse CRS from JSON, binary, hex formats - [ ] Execute all 5 validation stages - [ ] Output human-readable verification report - [ ] Machine-parseable JSON output mode - [ ] Multi-CRS support (AND-of-2 verification) - [ ] Ceremony transcript cross-verification - [ ] Timing measurement (detect non-constant-time) - [ ] Digest output for protocol integration **Usage examples:** ```bash # Basic verification $ pvugc-verify-crs --crs crs.json [Output: human-readable report] # JSON output for automation $ pvugc-verify-crs --crs crs.json --format json > result.json # Multi-CRS verification $ pvugc-verify-crs --crs crs1.json --crs crs2.json --multi # With ceremony transcript $ pvugc-verify-crs --crs crs.json --transcript ceremony.json # Output digest only (for scripts) $ pvugc-verify-crs --crs crs.json --output-digest 0xabc123def456789abcdef0123456789abcdef0123456789abcdef0123456789 ``` **Acceptance criteria:** - [ ] Tool validates against all 11 test vectors - [ ] Human-readable and JSON output modes - [ ] Multi-CRS support implemented - [ ] Ceremony transcript verification - [ ] Distributed as standalone binary (Linux, macOS, Windows) - [ ] Documentation published --- **R8: Document CRS Ceremony Best Practices** **Priority:** P2 | **Timeline:** 2 weeks **Deliverable:** Comprehensive ceremony guide (see Finding 7.2) **Content:** - [ ] MPC ceremony structure (3 phases) - [ ] Participant recruitment guidelines - [ ] Randomness source requirements - [ ] Round-by-round execution protocol - [ ] Transcript format specification (JSON schema) - [ ] Security considerations (threat model, mitigations) - [ ] Verification procedures (post-ceremony) - [ ] Case studies (example ceremonies) **Publication:** - Add to specification as Appendix B: "CRS Ceremony Best Practices" - Publish standalone guide: `docs/crs_ceremony_guide.md` - Include in protocol documentation website **Acceptance criteria:** - [ ] Complete ceremony protocol documented - [ ] Transcript JSON schema provided - [ ] Security audit checklist included - [ ] Example ceremony transcript published --- **R9: Require CRS Ceremony Audit Trail** **Priority:** P1 | **Timeline:** Before first ceremony **Deliverable:** Normative audit trail requirements (see Finding 7.4) **Proposed normative text (add to Β§93):** ```markdown **Audit Trail Requirements (MUST):** Ceremony coordinators MUST publish a complete audit trail including: 1. **Transcript File:** - JSON format per schema in Appendix C - Round-by-round execution log - Cryptographic commitments and proofs - PGP signatures from all participants - SHA-256 digest of transcript 2. **Multimedia Documentation:** - Video recording of ceremony (full session) - Live stream archive (if applicable) - Chat transcript (secure communication log) - Photograph documentation (participant verification) 3. **Security Documentation:** - Randomness source documentation - Entropy samples (verifiable) - Independent security audit report - Post-ceremony verification log 4. **Publication:** - Upload to public archive (IPFS, Arweave, GitHub) - Provide multiple access methods (redundancy) - Include SHA-256 digest in protocol documentation - Enable community verification **Verification Period (SHOULD):** Allow minimum 7 days for independent verification before using CRS in production. Ceremony coordinators SHOULD collect and publish independent verification attestations. ``` **Acceptance criteria:** - [ ] Audit trail requirements added to Β§93 - [ ] JSON transcript schema specified (Appendix C) - [ ] Publication requirements defined - [ ] Verification period recommendation included --- ## Validation Checklist **Specification:** - [ ] Canonical algorithm added to Β§92 (ValidateCrsAndComputeDigest) - [ ] Binding check required before digest computation - [ ] Constant-time comparison mandated in Β§92 step 3 - [ ] G2 cofactor clearing requirement explicit (hβ‚‚ β‰ˆ 2^128) - [ ] Multi-CRS independence requirements in Β§93 - [ ] CRS ceremony best practices documented (Appendix B) - [ ] Audit trail requirements specified in Β§93 - [ ] Transcript JSON schema provided (Appendix C) **Implementation:** - [ ] Binding check `e(u₁, v₁) β‰  e(uβ‚‚, vβ‚‚)` implemented - [ ] Constant-time comparison used (subtle crate or equivalent) - [ ] G1 subgroup membership verified (automatic with h₁=1) - [ ] G2 subgroup membership verified (cofactor clearing hβ‚‚β‰ˆ2^128) - [ ] Identity element rejection implemented - [ ] Canonical serialization (compressed, big-endian) - [ ] Domain separation tags ("PVUGC/GS-CRS/v1", "BINDING_SXDH") - [ ] Multi-CRS digest computation (AND-of-2) - [ ] Error handling (graceful, no exceptions leak) **Testing:** - [ ] Test vector suite published (11 comprehensive cases) - [ ] All test vectors pass in reference implementation - [ ] Fuzzing harness (1M+ iterations without crashes) - [ ] Side-channel test (constant-time verification) - [ ] Integration tests (end-to-end validation) - [ ] Performance benchmarks (< 10ms validation time) **Tooling:** - [ ] Reference implementation published (Rust crate) - [ ] Binding verification tool available (pvugc-verify-crs) - [ ] Ceremony helper tools (MPC protocol implementation) - [ ] Transcript verification tool (cross-check ceremony) - [ ] Test vector generator and validator scripts **Ceremony:** - [ ] Minimum 2 independent CRS ceremonies conducted - [ ] Each ceremony meets independence criteria (5 requirements) - [ ] Transcripts published (JSON format, PGP signed) - [ ] Video recordings available (public archive) - [ ] Security audits completed (independent cryptographers) - [ ] Community verification period (7+ days) - [ ] Independent verification attestations collected (10+ verifiers) **Security:** - [ ] External security review completed - [ ] Constant-time property verified (valgrind, dudect) - [ ] Fuzzing results clean (no crashes, no hangs) - [ ] Side-channel analysis (no timing leaks) - [ ] Threat model documented - [ ] Attack scenarios validated (10.1, 10.2, 10.3, 10.4) --- ## Status Decision **Final Severity:** 🟒 Low **Justification:** - Binding CRS requirement is procedural control (ceremony assumed honest) - Risk mitigated by multi-CRS defense (requires compromising multiple ceremonies) - Detection mechanism (binding check) is mathematically sound - Impact limited to soundness of GS attestation layer (does not affect Bitcoin consensus) **Final Status:** βœ… Resolved (cryptographically sound, pending implementation) **Acceptance Criteria:** **Phase 1: Specification (Required for status "Fully Resolved")** - [x] v2.0 binding CRS requirement (Β§89-91, lines 208-210) - DONE - [ ] Canonical algorithm in specification (Β§92) - PENDING - [ ] Ceremony requirements documented (Β§93) - PENDING - [ ] Test vector suite published - PENDING **Phase 2: Implementation (Required for production deployment)** - [ ] Reference implementation verified (external review) - [ ] Binding verification tool available - [ ] Minimum 2 independent CRS ceremonies conducted - [ ] Ceremony transcripts published and verified **Phase 3: Security Validation (Required for mainnet)** - [ ] External security audit completed - [ ] Community verification period (7+ days) - [ ] Independent verification attestations (10+ verifiers) - [ ] No critical issues found during verification period **Recommended Path Forward:** **Immediate (Week 1-2):** 1. Add M2's canonical algorithm to PVUGC-2025-10-20.md Β§1 Introduction as Β§92 2. Specify CRS ceremony requirements as Β§93 3. Begin reference implementation in Rust **Short-term (Week 3-6):** 4. Complete reference implementation and test vectors 5. Develop binding verification tool (pvugc-verify-crs) 6. Publish ceremony best practices guide **Medium-term (Week 7-12):** 7. Conduct first CRS ceremony (ceremony A) 8. Conduct second CRS ceremony (ceremony B) 9. Community verification period (7 days each) 10. External security review **Long-term (Before mainnet):** 11. Integration testing with full PVUGC protocol 12. Security audit findings resolution 13. Community consensus on CRS acceptance 14. Final go/no-go decision for production --- ## Related Issues **Directly Related:** - **PVUGC-002:** Multi-CRS AND-ing (βœ… resolved - provides defense-in-depth) - Multi-CRS requirement mitigates ceremony compromise - Binding CRS requirement essential for GS soundness (Lemma 1) - **PVUGC-001:** GT-XPDH assumption (related - binding CRS ensures assumption properly applied) - Binding CRS required for GS product determinism (Lemma 1) - Non-binding CRS breaks independence property **Indirectly Related:** - **PVUGC-003:** Independence property (related - CRS structure affects independence) - Binding CRS ensures `U_j`, `V_k` independent of prover randomness - **PVUGC-005:** Context binding (related - CRS digest in ctx_hash) - `GS_instance_digest` includes CRS digest (digest chain) --- ## Appendices ### Appendix A: Algorithm Pseudocode (Complete) See M2's canonical algorithm (Appendix A10.M101) - validated and recommended for inclusion in specification Β§92. ### Appendix B: Mathematical Foundations **Groth-Sahai CRS Modes:** **Binding Mode (SXDH-based):** - Basis: `u₁ = (Ξ±Β·G₁, G₁)`, `uβ‚‚ = (Ξ²Β·G₁, G₁)` in 𝔾₁² - Dual: `v₁ = (Gβ‚‚, Ξ±Β·Gβ‚‚)`, `vβ‚‚ = (Gβ‚‚, Ξ²Β·Gβ‚‚)` in 𝔾₂² - Property: `e(u₁, v₁) = e(G₁, Gβ‚‚)^(Ξ±+1)`, `e(uβ‚‚, vβ‚‚) = e(G₁, Gβ‚‚)^(Ξ²+1)` - Binding: If Ξ± β‰  Ξ², then `e(u₁, v₁) β‰  e(uβ‚‚, vβ‚‚)` **Witness-Indistinguishable Mode:** - Perfectly orthogonal: `e(u₁, vβ‚‚) = e(uβ‚‚, v₁) = 1` - Implies: `e(u₁, v₁) = e(uβ‚‚, vβ‚‚)` - Commitments are perfectly hiding (zero-knowledge) **SXDH Assumption:** - DDH hard in both 𝔾₁ and 𝔾₂ - No efficiently computable isomorphism 𝔾₁ β†’ 𝔾₂ - Holds for Type-3 pairings (e.g., BLS12-381) **Reference:** Groth & Sahai (EUROCRYPT 2008), Section 3 ### Appendix C: Test Vector Specifications See Finding 6 for complete test vector specifications (11 cases across 5 categories). ### Appendix D: Ceremony Transcript Schema See Finding 7.4 for complete JSON schema specification. --- **Peer Review Metadata:** **Reviewers:** - **M1 (Primary Investigator):** Identified v1.0 gap, provided v2.0 resolution - **M2 (Mathematician):** Canonical algorithm specification, Round 3 validation - **Crypto-Reviewer (Lead):** Final comprehensive review with formal proofs **Review Dates:** - v1.0 Identification: 2025-10-07 - v2.0 Resolution: 2025-10-07 - M2 Deep-Dive: 2025-10-15 - Crypto-Reviewer Draft: 2025-10-15 - M2 Round 3 Validation: 2025-10-26 - Final Report: 2025-10-26 **Review Duration:** - M1: 2 hours (v1.0 + v2.0) - M2 Round 1: 3 hours (canonical algorithm) - Crypto-Reviewer: 4 hours (comprehensive analysis) - M2 Round 3: 2 hours (validation) - Total: 11 hours peer review **Documents Reviewed:** 6 files (v1.0, v2.0, M2 algorithm, spec, draft, M2 validation, template) **Cross-References Verified:** 12 spec locations **Test Vectors Specified:** 11 comprehensive cases **Attack Scenarios Analyzed:** 2 (both prevented) **Theorems Stated:** 4 (all validated) **Code Examples:** 3 (algorithm, Rust reference, CLI tool) **Quality Checklist (10/10 standards met):** - [x] 1. Evidence-backed claims with spec line references - [x] 2. Formal mathematical rigor (4 theorems, proofs) - [x] 3. Complete attack catalog (2 scenarios analyzed) - [x] 4. Normative text proposals (9 recommendations) - [x] 5. Validation checklist (7 categories, 40+ items) - [x] 6. Cross-references to v1.0, v2.0, final spec - [x] 7. Clear severity/status justification - [x] 8. Practical deployment guidance (ceremony, tooling) - [x] 9. No ambiguous conclusions (clear acceptance criteria) - [x] 10. TEMPLATE.md structure compliance **Collaboration Notes:** - M1's v1.0 concern: βœ… Valid - tag mechanism underspecified - M1's v2.0 resolution: βœ… Valid - binding requirement + digest pinning correct - M2's canonical algorithm: βœ… Valid - complete, correct, implementable - M2's Round 3 revisions: βœ… All incorporated (R1-R4) - Enhancements: Test vectors expanded (3β†’11), tooling specified, ceremony guide - Disagreements: None - full agreement with M1 and M2 - Recommendations: All additive (no contradictions with prior work) **Acknowledgments:** - M1: Identified critical gap, provided clear v2.0 resolution - M2: Canonical algorithm eliminates implementation ambiguity, thorough Round 3 validation - Both: High-quality analysis, formal rigor, practical focus --- **Document Hash (SHA-256):** [To be computed after finalization] **PGP Signature:** [To be added by reviewer] --- END OF REPORT