threshold_bls/sig/
blind.rs

1use crate::group::{Element, Point, Scalar};
2use crate::sig::bls::{common::BLSScheme, BLSError};
3use crate::sig::{BlindScheme, Scheme};
4use rand_core::RngCore;
5use serde::{Deserialize, Serialize};
6use thiserror::Error;
7
8/// BlindError are errors which may be returned from a blind signature scheme
9#[derive(Debug, Error)]
10pub enum BlindError {
11    /// InvalidToken is thrown out when the token used to unblind can not be
12    /// inversed. This error should not happen if you use the Token that was
13    /// returned by the blind operation.
14    #[error("invalid token")]
15    InvalidToken,
16
17    /// Raised when (de)serialization fails
18    #[error("could not deserialize: {0}")]
19    BincodeError(#[from] bincode::Error),
20
21    #[error("invalid signature verification: {0}")]
22    SignatureError(#[from] BLSError),
23}
24
25/// Blinding a message before requesting a signature requires the usage of a
26/// private blinding factor that is called a Token. To unblind the signature
27/// afterwards, one needs the same token as what the blinding method returned.
28/// In this blind signature scheme, the token is simply a field element.
29#[derive(Clone, Debug, Serialize, Deserialize)]
30#[serde(bound = "S: Serialize + serde::de::DeserializeOwned")]
31pub struct Token<S: Scalar>(S);
32
33impl<S: Scalar> Default for Token<S> {
34    fn default() -> Self {
35        Self::new()
36    }
37}
38
39impl<S: Scalar> Token<S> {
40    /// Instantiates a token with the `Zero` element of the underlying scalar
41    pub fn new() -> Self {
42        Self(S::new())
43    }
44}
45
46/// The blinder follows the protocol described
47/// in this [paper](https://eprint.iacr.org/2018/733.pdf).
48impl<I> BlindScheme for I
49where
50    I: Scheme + BLSScheme,
51{
52    type Token = Token<I::Private>;
53    type Error = BlindError;
54
55    fn blind_msg<R: RngCore>(msg: &[u8], rng: &mut R) -> (Self::Token, Vec<u8>) {
56        let r = I::Private::rand(rng);
57
58        let mut h = I::Signature::new();
59
60        // r * H(m)
61        // XXX result from zexe API but it shouldn't
62        h.map(msg).expect("could not map to the group");
63        h.mul(&r);
64
65        let serialized = bincode::serialize(&h).expect("serialization should not fail");
66        (Token(r), serialized)
67    }
68
69    fn unblind_sig(t: &Self::Token, sigbuff: &[u8]) -> Result<Vec<u8>, Self::Error> {
70        let mut sig: I::Signature = bincode::deserialize(sigbuff)?;
71
72        // r^-1 * ( r * H(m)^x) = H(m)^x
73        let ri = t.0.inverse().ok_or(BlindError::InvalidToken)?;
74        sig.mul(&ri);
75
76        let serialized = bincode::serialize(&sig)?;
77        Ok(serialized)
78    }
79
80    fn blind_verify(
81        public: &I::Public,
82        blinded_msg: &[u8],
83        blinded_sig: &[u8],
84    ) -> Result<(), Self::Error> {
85        // message point
86        let blinded_msg: I::Signature = bincode::deserialize(blinded_msg)?;
87        // signature point
88        let blinded_sig: I::Signature = bincode::deserialize(blinded_sig)?;
89
90        if !I::final_exp(public, &blinded_sig, &blinded_msg) {
91            return Err(BlindError::from(BLSError::InvalidSig));
92        }
93        Ok(())
94    }
95
96    fn blind_sign(private: &I::Private, blinded_msg: &[u8]) -> Result<Vec<u8>, Self::Error> {
97        // (r * H(m))^x
98        let mut hm: I::Signature = bincode::deserialize(blinded_msg)?;
99        hm.mul(private);
100        Ok(bincode::serialize(&hm)?)
101    }
102}
103
104#[cfg(test)]
105#[cfg(feature = "bls12_381")]
106mod tests {
107    use super::*;
108    use crate::curve::bls12381::PairingCurve as PCurve;
109    use crate::sig::bls::{G1Scheme, G2Scheme};
110    use crate::sig::SignatureScheme;
111    use rand::thread_rng;
112
113    #[cfg(feature = "bls12_381")]
114    #[test]
115    fn blind_g1() {
116        blind_test::<G1Scheme<PCurve>>();
117    }
118
119    #[cfg(feature = "bls12_381")]
120    #[test]
121    fn blind_g2() {
122        blind_test::<G2Scheme<PCurve>>();
123    }
124
125    fn blind_test<B>()
126    where
127        B: BlindScheme + SignatureScheme,
128    {
129        let (private, public) = B::keypair(&mut thread_rng());
130        let msg = vec![1, 9, 6, 9];
131
132        let (token, blinded) = B::blind_msg(&msg, &mut thread_rng());
133
134        // signs the blinded message w/o hashing
135        let blinded_sig = B::blind_sign(&private, &blinded).unwrap();
136        B::blind_verify(&public, &blinded, &blinded_sig).unwrap();
137
138        let clear_sig = B::unblind_sig(&token, &blinded_sig).expect("unblind should go well");
139        B::verify(&public, &msg, &clear_sig).unwrap();
140    }
141}