use crate::group::{Element, Point, Scalar};
use crate::sig::bls::{common::BLSScheme, BLSError};
use crate::sig::{BlindScheme, Scheme};
use rand_core::RngCore;
use serde::{Deserialize, Serialize};
use thiserror::Error;
#[derive(Debug, Error)]
pub enum BlindError {
#[error("invalid token")]
InvalidToken,
#[error("could not deserialize: {0}")]
BincodeError(#[from] bincode::Error),
#[error("invalid signature verification: {0}")]
SignatureError(#[from] BLSError),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(bound = "S: Serialize + serde::de::DeserializeOwned")]
pub struct Token<S: Scalar>(S);
impl<S: Scalar> Default for Token<S> {
fn default() -> Self {
Self::new()
}
}
impl<S: Scalar> Token<S> {
pub fn new() -> Self {
Self(S::new())
}
}
impl<I> BlindScheme for I
where
I: Scheme + BLSScheme,
{
type Token = Token<I::Private>;
type Error = BlindError;
fn blind_msg<R: RngCore>(msg: &[u8], rng: &mut R) -> (Self::Token, Vec<u8>) {
let r = I::Private::rand(rng);
let mut h = I::Signature::new();
h.map(msg).expect("could not map to the group");
h.mul(&r);
let serialized = bincode::serialize(&h).expect("serialization should not fail");
(Token(r), serialized)
}
fn unblind_sig(t: &Self::Token, sigbuff: &[u8]) -> Result<Vec<u8>, Self::Error> {
let mut sig: I::Signature = bincode::deserialize(sigbuff)?;
let ri = t.0.inverse().ok_or(BlindError::InvalidToken)?;
sig.mul(&ri);
let serialized = bincode::serialize(&sig)?;
Ok(serialized)
}
fn blind_verify(
public: &I::Public,
blinded_msg: &[u8],
blinded_sig: &[u8],
) -> Result<(), Self::Error> {
let blinded_msg: I::Signature = bincode::deserialize(blinded_msg)?;
let blinded_sig: I::Signature = bincode::deserialize(blinded_sig)?;
if !I::final_exp(public, &blinded_sig, &blinded_msg) {
return Err(BlindError::from(BLSError::InvalidSig));
}
Ok(())
}
fn blind_sign(private: &I::Private, blinded_msg: &[u8]) -> Result<Vec<u8>, Self::Error> {
let mut hm: I::Signature = bincode::deserialize(blinded_msg)?;
hm.mul(private);
Ok(bincode::serialize(&hm)?)
}
}
#[cfg(test)]
#[cfg(feature = "bls12_381")]
mod tests {
use super::*;
use crate::curve::bls12381::PairingCurve as PCurve;
use crate::sig::bls::{G1Scheme, G2Scheme};
use crate::sig::SignatureScheme;
use rand::thread_rng;
#[cfg(feature = "bls12_381")]
#[test]
fn blind_g1() {
blind_test::<G1Scheme<PCurve>>();
}
#[cfg(feature = "bls12_381")]
#[test]
fn blind_g2() {
blind_test::<G2Scheme<PCurve>>();
}
fn blind_test<B>()
where
B: BlindScheme + SignatureScheme,
{
let (private, public) = B::keypair(&mut thread_rng());
let msg = vec![1, 9, 6, 9];
let (token, blinded) = B::blind_msg(&msg, &mut thread_rng());
let blinded_sig = B::blind_sign(&private, &blinded).unwrap();
B::blind_verify(&public, &blinded, &blinded_sig).unwrap();
let clear_sig = B::unblind_sig(&token, &blinded_sig).expect("unblind should go well");
B::verify(&public, &msg, &clear_sig).unwrap();
}
}