threshold_bls/sig/
tblind.rs1use thiserror::Error;
2
3use crate::poly::{Eval, Poly};
4use crate::sig::tbls::Share;
5use crate::sig::{BlindScheme, BlindThresholdScheme, Partial, ThresholdScheme};
6
7#[derive(Debug, Error)]
8pub enum BlindThresholdError<E: 'static + std::error::Error> {
11 #[error(transparent)]
13 BlindError(E),
14
15 #[error(transparent)]
17 BincodeError(#[from] bincode::Error),
18}
19
20impl<T> BlindThresholdScheme for T
21where
22 T: 'static + ThresholdScheme + BlindScheme,
23{
24 type Error = BlindThresholdError<<T as BlindScheme>::Error>;
25
26 fn sign_blind_partial(
27 private: &Share<Self::Private>,
28 blinded_msg: &[u8],
29 ) -> Result<Partial, <Self as BlindThresholdScheme>::Error> {
30 let sig = Self::blind_sign(&private.private, blinded_msg)
31 .map_err(BlindThresholdError::BlindError)?;
32 let partial = Eval {
33 value: sig,
34 index: private.index,
35 };
36 bincode::serialize(&partial).map_err(BlindThresholdError::BincodeError)
37 }
38
39 fn unblind_partial_sig(
40 t: &Self::Token,
41 partial: &[u8],
42 ) -> Result<Partial, <Self as BlindThresholdScheme>::Error> {
43 let partial: Eval<Vec<u8>> = bincode::deserialize(partial)?;
45
46 let partially_unblinded =
47 Self::unblind_sig(t, &partial.value).map_err(BlindThresholdError::BlindError)?;
48 let partially_unblinded = Eval {
49 index: partial.index,
50 value: partially_unblinded,
51 };
52 bincode::serialize(&partially_unblinded).map_err(BlindThresholdError::BincodeError)
53 }
54
55 fn verify_blind_partial(
56 public: &Poly<Self::Public>,
57 blind_msg: &[u8],
58 blind_partial: &[u8],
59 ) -> Result<(), <Self as BlindThresholdScheme>::Error> {
60 let blinded_partial: Eval<Vec<u8>> = bincode::deserialize(blind_partial)?;
61 let public_i = public.eval(blinded_partial.index);
62 Self::blind_verify(&public_i.value, blind_msg, &blinded_partial.value)
63 .map_err(BlindThresholdError::BlindError)
64 }
65}
66
67#[cfg(test)]
68mod tests {
69 use rand::thread_rng;
70
71 #[cfg(feature = "bls12_381")]
72 use crate::curve::bls12381::PairingCurve as PCurve;
73 use crate::poly::Idx;
74 use crate::sig::{
75 bls::{G1Scheme, G2Scheme},
76 SignatureScheme,
77 };
78
79 use super::*;
80
81 fn shares<B: BlindThresholdScheme>(
82 n: usize,
83 t: usize,
84 ) -> (Vec<Share<B::Private>>, Poly<B::Public>) {
85 let private = Poly::<B::Private>::new(t - 1);
86 let shares = (0..n)
87 .map(|i| private.eval(i as Idx))
88 .map(|e| Share {
89 index: e.index,
90 private: e.value,
91 })
92 .collect();
93 (shares, private.commit())
94 }
95
96 #[cfg(feature = "bls12_381")]
97 #[test]
98 fn tblind_g1_bellman_unblind() {
99 tblind_test::<G1Scheme<PCurve>>();
100 }
101
102 #[cfg(feature = "bls12_381")]
103 #[test]
104 fn tblind_g2_bellman_unblind() {
105 tblind_test::<G2Scheme<PCurve>>();
106 }
107
108 fn tblind_test<B>()
109 where
110 B: BlindThresholdScheme + SignatureScheme + ThresholdScheme,
111 {
112 let n = 5;
113 let thr = 4;
114 let (shares, public) = shares::<B>(n, thr);
115 let msg = vec![1, 9, 6, 9];
116
117 let (token, blinded) = B::blind_msg(&msg, &mut thread_rng());
119
120 let partials: Vec<_> = shares
122 .iter()
123 .map(|share| B::sign_blind_partial(share, &blinded).unwrap())
124 .collect();
125
126 assert_eq!(
128 false,
129 partials
130 .iter()
131 .any(|p| B::verify_blind_partial(&public, &blinded, p).is_err())
132 );
133
134 let unblindeds_partials: Vec<_> = partials
136 .iter()
137 .map(|p| B::unblind_partial_sig(&token, p).unwrap())
138 .collect();
139
140 let final_sig1 = B::aggregate(thr, &unblindeds_partials).unwrap();
142 B::verify(&public.public_key(), &msg, &final_sig1).unwrap();
143
144 let blinded_final = B::aggregate(thr, &partials).unwrap();
147
148 let final_sig2 = B::unblind_sig(&token, &blinded_final).unwrap();
150
151 B::verify(&public.public_key(), &msg, &final_sig2).unwrap();
153 assert_eq!(final_sig1, final_sig2);
154 }
155}