1use crate::signing::{KeyPair, PublicKey, verify as verify_signature};
35use blake3;
36use serde::{Deserialize, Serialize};
37use thiserror::Error;
38
39#[derive(Debug, Error)]
41pub enum RingError {
42 #[error("Ring must contain at least 2 public keys")]
43 RingTooSmall,
44
45 #[error("Signer not found in ring")]
46 SignerNotInRing,
47
48 #[error("Invalid ring signature")]
49 InvalidSignature,
50
51 #[error("Serialization error: {0}")]
52 SerializationError(String),
53
54 #[error("Ring size mismatch")]
55 RingSizeMismatch,
56}
57
58pub type RingResult<T> = Result<T, RingError>;
59
60#[derive(Debug, Clone, Serialize, Deserialize)]
65pub struct RingSignature {
66 commitments: Vec<[u8; 32]>,
68 #[serde(with = "serde_signature")]
70 signature: [u8; 64],
71 hint: u32,
73}
74
75mod serde_signature {
77 use serde::{Deserialize, Deserializer, Serializer};
78
79 pub fn serialize<S>(bytes: &[u8; 64], serializer: S) -> Result<S::Ok, S::Error>
80 where
81 S: Serializer,
82 {
83 serializer.serialize_bytes(bytes)
84 }
85
86 pub fn deserialize<'de, D>(deserializer: D) -> Result<[u8; 64], D::Error>
87 where
88 D: Deserializer<'de>,
89 {
90 let bytes: Vec<u8> = Deserialize::deserialize(deserializer)?;
91 if bytes.len() != 64 {
92 return Err(serde::de::Error::custom("invalid signature length"));
93 }
94 let mut array = [0u8; 64];
95 array.copy_from_slice(&bytes);
96 Ok(array)
97 }
98}
99
100impl RingSignature {
101 pub fn to_bytes(&self) -> RingResult<Vec<u8>> {
103 crate::codec::encode(self).map_err(|e| RingError::SerializationError(e.to_string()))
104 }
105
106 pub fn from_bytes(bytes: &[u8]) -> RingResult<Self> {
108 crate::codec::decode(bytes).map_err(|e| RingError::SerializationError(e.to_string()))
109 }
110
111 pub fn ring_size(&self) -> usize {
113 self.commitments.len()
114 }
115}
116
117pub fn sign_ring(
127 signer: &KeyPair,
128 ring: &[PublicKey],
129 message: &[u8],
130) -> RingResult<RingSignature> {
131 if ring.len() < 2 {
132 return Err(RingError::RingTooSmall);
133 }
134
135 let signer_pubkey = signer.public_key();
137 let _signer_index = ring
138 .iter()
139 .position(|pk| pk == &signer_pubkey)
140 .ok_or(RingError::SignerNotInRing)?;
141
142 let mut commitments = Vec::with_capacity(ring.len());
144
145 for (i, pk) in ring.iter().enumerate() {
146 let mut hasher = blake3::Hasher::new();
148 hasher.update(b"CHIE-RING-SIG-V1");
149 hasher.update(message);
150 hasher.update(pk);
151 hasher.update(&i.to_le_bytes());
152
153 for ring_pk in ring {
155 hasher.update(ring_pk);
156 }
157
158 commitments.push(*hasher.finalize().as_bytes());
159 }
160
161 let mut sig_message = Vec::new();
164 sig_message.extend_from_slice(message);
165 for commitment in &commitments {
166 sig_message.extend_from_slice(commitment);
167 }
168
169 let signature = signer.sign(&sig_message);
170
171 let hint = blake3::hash(message).as_bytes()[0] as u32;
173
174 Ok(RingSignature {
175 commitments,
176 signature,
177 hint,
178 })
179}
180
181pub fn verify_ring(
187 ring: &[PublicKey],
188 message: &[u8],
189 signature: &RingSignature,
190) -> RingResult<bool> {
191 if ring.len() < 2 {
192 return Err(RingError::RingTooSmall);
193 }
194
195 if ring.len() != signature.commitments.len() {
196 return Err(RingError::RingSizeMismatch);
197 }
198
199 for (i, pk) in ring.iter().enumerate() {
201 let mut hasher = blake3::Hasher::new();
202 hasher.update(b"CHIE-RING-SIG-V1");
203 hasher.update(message);
204 hasher.update(pk);
205 hasher.update(&i.to_le_bytes());
206
207 for ring_pk in ring {
208 hasher.update(ring_pk);
209 }
210
211 let expected_commitment = hasher.finalize();
212 if expected_commitment.as_bytes() != &signature.commitments[i] {
213 return Ok(false);
214 }
215 }
216
217 let mut sig_message = Vec::new();
219 sig_message.extend_from_slice(message);
220 for commitment in &signature.commitments {
221 sig_message.extend_from_slice(commitment);
222 }
223
224 for pk in ring {
226 if verify_signature(pk, &sig_message, &signature.signature).is_ok() {
227 return Ok(true);
228 }
229 }
230
231 Ok(false)
232}
233
234pub struct RingSignatureBuilder {
236 ring: Vec<PublicKey>,
237 context: Vec<u8>,
238}
239
240impl RingSignatureBuilder {
241 pub fn new() -> Self {
243 Self {
244 ring: Vec::new(),
245 context: Vec::new(),
246 }
247 }
248
249 pub fn add_member(mut self, pubkey: PublicKey) -> Self {
251 self.ring.push(pubkey);
252 self
253 }
254
255 pub fn add_members(mut self, pubkeys: &[PublicKey]) -> Self {
257 self.ring.extend_from_slice(pubkeys);
258 self
259 }
260
261 pub fn with_context(mut self, context: &[u8]) -> Self {
263 self.context = context.to_vec();
264 self
265 }
266
267 pub fn sign(self, signer: &KeyPair, message: &[u8]) -> RingResult<RingSignature> {
269 let mut combined_message = self.context;
270 combined_message.extend_from_slice(message);
271 sign_ring(signer, &self.ring, &combined_message)
272 }
273
274 pub fn verify(self, message: &[u8], signature: &RingSignature) -> RingResult<bool> {
276 let mut combined_message = self.context;
277 combined_message.extend_from_slice(message);
278 verify_ring(&self.ring, &combined_message, signature)
279 }
280}
281
282impl Default for RingSignatureBuilder {
283 fn default() -> Self {
284 Self::new()
285 }
286}
287
288#[cfg(test)]
289mod tests {
290 use super::*;
291 use crate::signing::KeyPair;
292
293 #[test]
294 fn test_ring_signature_basic() {
295 let keypair1 = KeyPair::generate();
296 let keypair2 = KeyPair::generate();
297 let keypair3 = KeyPair::generate();
298
299 let ring = vec![
300 keypair1.public_key(),
301 keypair2.public_key(),
302 keypair3.public_key(),
303 ];
304
305 let message = b"Test message for ring signature";
306
307 let signature = sign_ring(&keypair2, &ring, message).unwrap();
309
310 assert!(verify_ring(&ring, message, &signature).unwrap());
312 }
313
314 #[test]
315 fn test_ring_signature_wrong_message() {
316 let keypair1 = KeyPair::generate();
317 let keypair2 = KeyPair::generate();
318 let keypair3 = KeyPair::generate();
319
320 let ring = vec![
321 keypair1.public_key(),
322 keypair2.public_key(),
323 keypair3.public_key(),
324 ];
325
326 let message = b"Original message";
327 let wrong_message = b"Wrong message";
328
329 let signature = sign_ring(&keypair2, &ring, message).unwrap();
330
331 assert!(!verify_ring(&ring, wrong_message, &signature).unwrap());
333 }
334
335 #[test]
336 fn test_ring_too_small() {
337 let keypair1 = KeyPair::generate();
338 let ring = vec![keypair1.public_key()];
339 let message = b"Test";
340
341 let result = sign_ring(&keypair1, &ring, message);
342 assert!(matches!(result, Err(RingError::RingTooSmall)));
343 }
344
345 #[test]
346 fn test_signer_not_in_ring() {
347 let keypair1 = KeyPair::generate();
348 let keypair2 = KeyPair::generate();
349 let keypair3 = KeyPair::generate();
350 let outsider = KeyPair::generate();
351
352 let ring = vec![
353 keypair1.public_key(),
354 keypair2.public_key(),
355 keypair3.public_key(),
356 ];
357
358 let message = b"Test";
359 let result = sign_ring(&outsider, &ring, message);
360 assert!(matches!(result, Err(RingError::SignerNotInRing)));
361 }
362
363 #[test]
364 fn test_ring_signature_serialization() {
365 let keypair1 = KeyPair::generate();
366 let keypair2 = KeyPair::generate();
367 let keypair3 = KeyPair::generate();
368
369 let ring = vec![
370 keypair1.public_key(),
371 keypair2.public_key(),
372 keypair3.public_key(),
373 ];
374
375 let message = b"Test serialization";
376 let signature = sign_ring(&keypair2, &ring, message).unwrap();
377
378 let bytes = signature.to_bytes().unwrap();
380 let deserialized = RingSignature::from_bytes(&bytes).unwrap();
381
382 assert!(verify_ring(&ring, message, &deserialized).unwrap());
384 }
385
386 #[test]
387 fn test_ring_signature_builder() {
388 let keypair1 = KeyPair::generate();
389 let keypair2 = KeyPair::generate();
390 let keypair3 = KeyPair::generate();
391
392 let message = b"Builder test";
393
394 let signature = RingSignatureBuilder::new()
395 .add_member(keypair1.public_key())
396 .add_member(keypair2.public_key())
397 .add_member(keypair3.public_key())
398 .with_context(b"CHIE-PROTOCOL-V1")
399 .sign(&keypair2, message)
400 .unwrap();
401
402 let valid = RingSignatureBuilder::new()
403 .add_member(keypair1.public_key())
404 .add_member(keypair2.public_key())
405 .add_member(keypair3.public_key())
406 .with_context(b"CHIE-PROTOCOL-V1")
407 .verify(message, &signature)
408 .unwrap();
409
410 assert!(valid);
411 }
412
413 #[test]
414 fn test_large_ring() {
415 let keypairs: Vec<KeyPair> = (0..10).map(|_| KeyPair::generate()).collect();
417 let ring: Vec<PublicKey> = keypairs.iter().map(|kp| kp.public_key()).collect();
418
419 let message = b"Large ring test";
420 let signer = &keypairs[5];
421
422 let signature = sign_ring(signer, &ring, message).unwrap();
423 assert!(verify_ring(&ring, message, &signature).unwrap());
424 }
425
426 #[test]
427 fn test_ring_anonymity() {
428 let keypair1 = KeyPair::generate();
430 let keypair2 = KeyPair::generate();
431 let keypair3 = KeyPair::generate();
432
433 let ring = vec![
434 keypair1.public_key(),
435 keypair2.public_key(),
436 keypair3.public_key(),
437 ];
438
439 let message = b"Anonymity test";
440
441 let sig1 = sign_ring(&keypair1, &ring, message).unwrap();
442 let sig2 = sign_ring(&keypair2, &ring, message).unwrap();
443
444 assert!(verify_ring(&ring, message, &sig1).unwrap());
446 assert!(verify_ring(&ring, message, &sig2).unwrap());
447
448 assert_ne!(sig1.signature, sig2.signature);
450 }
451}