use crate::arithmetic::scalars::ScalarNonZero;
use crate::keys::*;
use derive_more::{Deref, From};
use rand_core::{CryptoRng, Rng};
#[derive(Copy, Clone, Debug, From, Deref)]
pub struct BlindingFactor(pub(crate) ScalarNonZero);
#[derive(Copy, Clone, Eq, PartialEq, Debug, From, Deref)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(transparent))]
pub struct BlindedPseudonymGlobalSecretKey(pub(crate) ScalarNonZero);
#[derive(Copy, Clone, Eq, PartialEq, Debug, From, Deref)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(transparent))]
pub struct BlindedAttributeGlobalSecretKey(pub(crate) ScalarNonZero);
#[derive(Copy, Clone, Eq, PartialEq, Debug, From)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct BlindedGlobalKeys {
pub pseudonym: BlindedPseudonymGlobalSecretKey,
pub attribute: BlindedAttributeGlobalSecretKey,
}
impl BlindingFactor {
pub fn random<R: Rng + CryptoRng>(rng: &mut R) -> Self {
loop {
let scalar = ScalarNonZero::random(rng);
if scalar != ScalarNonZero::one() {
return Self(scalar);
}
}
}
pub fn from_bytes(bytes: &[u8; 32]) -> Option<Self> {
ScalarNonZero::from_bytes(bytes).map(Self)
}
pub fn from_slice(slice: &[u8]) -> Option<Self> {
ScalarNonZero::from_slice(slice).map(Self)
}
pub fn from_hex(s: &str) -> Option<Self> {
ScalarNonZero::from_hex(s).map(Self)
}
}
impl BlindedPseudonymGlobalSecretKey {
pub fn from_bytes(bytes: &[u8; 32]) -> Option<Self> {
ScalarNonZero::from_bytes(bytes).map(Self)
}
pub fn from_slice(slice: &[u8]) -> Option<Self> {
ScalarNonZero::from_slice(slice).map(Self)
}
pub fn from_hex(s: &str) -> Option<Self> {
ScalarNonZero::from_hex(s).map(Self)
}
}
impl BlindedAttributeGlobalSecretKey {
pub fn from_bytes(bytes: &[u8; 32]) -> Option<Self> {
ScalarNonZero::from_bytes(bytes).map(Self)
}
pub fn from_slice(slice: &[u8]) -> Option<Self> {
ScalarNonZero::from_slice(slice).map(Self)
}
pub fn from_hex(s: &str) -> Option<Self> {
ScalarNonZero::from_hex(s).map(Self)
}
}
fn compute_blinding_multiplier(blinding_factors: &[BlindingFactor]) -> Option<ScalarNonZero> {
let k = blinding_factors
.iter()
.fold(ScalarNonZero::one(), |acc, x| acc * x.0.invert());
if k == ScalarNonZero::one() {
return None;
}
Some(k)
}
pub trait BlindableGlobalSecretKey: Sized {
type BlindedType: From<ScalarNonZero>;
fn inner(&self) -> &ScalarNonZero;
fn blind(&self, blinding_factors: &[BlindingFactor]) -> Option<Self::BlindedType> {
compute_blinding_multiplier(blinding_factors)
.map(|k| Self::BlindedType::from(*self.inner() * k))
}
}
impl BlindableGlobalSecretKey for PseudonymGlobalSecretKey {
type BlindedType = BlindedPseudonymGlobalSecretKey;
fn inner(&self) -> &ScalarNonZero {
&self.0
}
}
impl BlindableGlobalSecretKey for AttributeGlobalSecretKey {
type BlindedType = BlindedAttributeGlobalSecretKey;
fn inner(&self) -> &ScalarNonZero {
&self.0
}
}
pub fn make_blinded_global_key<K>(
global_secret_key: &K,
blinding_factors: &[BlindingFactor],
) -> Option<K::BlindedType>
where
K: BlindableGlobalSecretKey,
{
global_secret_key.blind(blinding_factors)
}
pub fn make_blinded_pseudonym_global_secret_key(
global_secret_key: &PseudonymGlobalSecretKey,
blinding_factors: &[BlindingFactor],
) -> Option<BlindedPseudonymGlobalSecretKey> {
make_blinded_global_key(global_secret_key, blinding_factors)
}
pub fn make_blinded_attribute_global_secret_key(
global_secret_key: &AttributeGlobalSecretKey,
blinding_factors: &[BlindingFactor],
) -> Option<BlindedAttributeGlobalSecretKey> {
make_blinded_global_key(global_secret_key, blinding_factors)
}
pub fn make_blinded_global_keys(
pseudonym_global_secret_key: &PseudonymGlobalSecretKey,
attribute_global_secret_key: &AttributeGlobalSecretKey,
blinding_factors: &[BlindingFactor],
) -> Option<BlindedGlobalKeys> {
let pseudonym = make_blinded_global_key(pseudonym_global_secret_key, blinding_factors)?;
let attribute = make_blinded_global_key(attribute_global_secret_key, blinding_factors)?;
Some(BlindedGlobalKeys {
pseudonym,
attribute,
})
}