Skip to main content

confium_ring/
lib.rs

1//! Threshold ring signatures — research prototype (P3).
2//!
3//! For sensitive national-security type approvals: hide WHICH
4//! directors signed. Public can verify the signature; watchdogs
5//! know SOMETHING was signed; signer identities anonymized among
6//! the eligible set; revealed only to designated auditor.
7//!
8//! Currently no production-quality threshold ring signature
9//! implementation exists. This is research frontier — long horizon
10//! beyond Q2 2027 NIST MPTS submission.
11//!
12//! See `TODO.roadmap/39-threshold-ring-signatures.md` for full spec.
13
14#![forbid(unsafe_code)]
15#![allow(missing_docs)] // TODO: document before 1.0
16
17use serde::{Deserialize, Serialize};
18
19/// A ring signature — anonymous signature on behalf of a ring of eligible signers.
20#[derive(Debug, Clone, Serialize, Deserialize)]
21pub struct RingSignature {
22    /// All eligible signers' public keys (the "ring").
23    pub ring_members: Vec<Vec<u8>>,
24    /// The signature itself.
25    pub signature: Vec<u8>,
26    /// How many ring members collaborated to produce this signature (T).
27    pub signer_count: u32,
28    /// Optional auditor-encrypted identity evidence.
29    pub auditor_evidence: Option<Vec<u8>>,
30}
31
32/// Errors during ring signature operations.
33#[derive(Debug, thiserror::Error)]
34pub enum RingError {
35    /// Ring too small.
36    #[error("ring too small: {0} members")]
37    RingTooSmall(usize),
38    /// Signer count exceeds ring size.
39    #[error("signer_count {signer_count} exceeds ring size {ring_size}")]
40    SignerCountExceeds {
41        /// Number of signers.
42        signer_count: u32,
43        /// Ring size.
44        ring_size: usize,
45    },
46    /// Research-only operation.
47    #[error("threshold ring signatures are research-only (P3): {0}")]
48    ResearchOnly(String),
49}
50
51/// Verify the structural validity of a ring signature (not the crypto).
52pub fn validate_structure(sig: &RingSignature) -> Result<(), RingError> {
53    if sig.ring_members.len() < 2 {
54        return Err(RingError::RingTooSmall(sig.ring_members.len()));
55    }
56    if sig.signer_count as usize > sig.ring_members.len() {
57        return Err(RingError::SignerCountExceeds {
58            signer_count: sig.signer_count,
59            ring_size: sig.ring_members.len(),
60        });
61    }
62    Ok(())
63}
64
65#[cfg(test)]
66mod tests {
67    use super::*;
68
69    #[test]
70    fn valid_structure_passes() {
71        let sig = RingSignature {
72            ring_members: vec![vec![0u8; 32], vec![1u8; 32], vec![2u8; 32]],
73            signature: vec![0u8; 64],
74            signer_count: 2,
75            auditor_evidence: None,
76        };
77        validate_structure(&sig).unwrap();
78    }
79
80    #[test]
81    fn ring_too_small_fails() {
82        let sig = RingSignature {
83            ring_members: vec![vec![0u8; 32]],
84            signature: vec![0u8; 64],
85            signer_count: 1,
86            auditor_evidence: None,
87        };
88        let result = validate_structure(&sig);
89        assert!(matches!(result, Err(RingError::RingTooSmall(_))));
90    }
91
92    #[test]
93    fn signer_count_exceeds_fails() {
94        let sig = RingSignature {
95            ring_members: vec![vec![0u8; 32], vec![1u8; 32]],
96            signature: vec![0u8; 64],
97            signer_count: 3,
98            auditor_evidence: None,
99        };
100        let result = validate_structure(&sig);
101        assert!(matches!(result, Err(RingError::SignerCountExceeds { .. })));
102    }
103}