use crate::arithmetic::py::scalars::PyScalarNonZero;
use crate::arithmetic::scalars::ScalarTraits;
use crate::keys::distribution::*;
use crate::keys::py::types::{
PyAttributeGlobalSecretKey, PyGlobalSecretKeys, PyPseudonymGlobalSecretKey,
};
use crate::keys::types::{AttributeGlobalSecretKey, PseudonymGlobalSecretKey};
use derive_more::{Deref, From, Into};
use pyo3::prelude::*;
use pyo3::types::{PyAny, PyBytes};
use pyo3::Py;
#[derive(Copy, Clone, Debug, From, Into, Deref)]
#[pyclass(name = "BlindingFactor", from_py_object)]
pub struct PyBlindingFactor(pub(crate) BlindingFactor);
#[pymethods]
impl PyBlindingFactor {
#[new]
fn new(x: PyScalarNonZero) -> Self {
PyBlindingFactor(BlindingFactor(x.0))
}
#[staticmethod]
#[pyo3(name = "random")]
fn random() -> Self {
let mut rng = rand::rng();
let x = BlindingFactor::random(&mut rng);
PyBlindingFactor(x)
}
#[pyo3(name = "to_bytes")]
fn encode(&self, py: Python) -> Py<PyAny> {
PyBytes::new(py, &self.0.to_bytes()).into()
}
#[staticmethod]
#[pyo3(name = "from_bytes")]
fn decode(bytes: &[u8]) -> Option<PyBlindingFactor> {
BlindingFactor::from_slice(bytes).map(PyBlindingFactor)
}
#[pyo3(name = "to_hex")]
fn as_hex(&self) -> String {
self.0.to_hex()
}
#[staticmethod]
#[pyo3(name = "from_hex")]
fn from_hex(hex: &str) -> Option<PyBlindingFactor> {
BlindingFactor::from_hex(hex).map(PyBlindingFactor)
}
fn __repr__(&self) -> String {
format!("BlindingFactor({})", self.as_hex())
}
fn __str__(&self) -> String {
self.as_hex()
}
fn __eq__(&self, other: &PyBlindingFactor) -> bool {
self.0 .0 == other.0 .0
}
}
#[derive(Copy, Clone, Eq, PartialEq, Debug, From, Into, Deref)]
#[pyclass(name = "BlindedPseudonymGlobalSecretKey", from_py_object)]
pub struct PyBlindedPseudonymGlobalSecretKey(pub(crate) BlindedPseudonymGlobalSecretKey);
#[pymethods]
impl PyBlindedPseudonymGlobalSecretKey {
#[new]
fn new(x: PyScalarNonZero) -> Self {
PyBlindedPseudonymGlobalSecretKey(BlindedPseudonymGlobalSecretKey(x.0))
}
#[pyo3(name = "to_bytes")]
fn encode(&self, py: Python) -> Py<PyAny> {
PyBytes::new(py, &self.0.to_bytes()).into()
}
#[staticmethod]
#[pyo3(name = "from_bytes")]
fn decode(bytes: &[u8]) -> Option<PyBlindedPseudonymGlobalSecretKey> {
BlindedPseudonymGlobalSecretKey::from_slice(bytes).map(PyBlindedPseudonymGlobalSecretKey)
}
#[pyo3(name = "to_hex")]
fn as_hex(&self) -> String {
self.0.to_hex()
}
#[staticmethod]
#[pyo3(name = "from_hex")]
fn from_hex(hex: &str) -> Option<PyBlindedPseudonymGlobalSecretKey> {
BlindedPseudonymGlobalSecretKey::from_hex(hex).map(PyBlindedPseudonymGlobalSecretKey)
}
fn __repr__(&self) -> String {
format!("BlindedPseudonymGlobalSecretKey({})", self.as_hex())
}
fn __str__(&self) -> String {
self.as_hex()
}
fn __eq__(&self, other: &PyBlindedPseudonymGlobalSecretKey) -> bool {
self.0 == other.0
}
}
#[derive(Copy, Clone, Eq, PartialEq, Debug, From, Into, Deref)]
#[pyclass(name = "BlindedAttributeGlobalSecretKey", from_py_object)]
pub struct PyBlindedAttributeGlobalSecretKey(pub(crate) BlindedAttributeGlobalSecretKey);
#[pymethods]
impl PyBlindedAttributeGlobalSecretKey {
#[new]
fn new(x: PyScalarNonZero) -> Self {
PyBlindedAttributeGlobalSecretKey(BlindedAttributeGlobalSecretKey(x.0))
}
#[pyo3(name = "to_bytes")]
fn encode(&self, py: Python) -> Py<PyAny> {
PyBytes::new(py, &self.0.to_bytes()).into()
}
#[staticmethod]
#[pyo3(name = "from_bytes")]
fn decode(bytes: &[u8]) -> Option<PyBlindedAttributeGlobalSecretKey> {
BlindedAttributeGlobalSecretKey::from_slice(bytes).map(PyBlindedAttributeGlobalSecretKey)
}
#[pyo3(name = "to_hex")]
fn as_hex(&self) -> String {
self.0.to_hex()
}
#[staticmethod]
#[pyo3(name = "from_hex")]
fn from_hex(hex: &str) -> Option<PyBlindedAttributeGlobalSecretKey> {
BlindedAttributeGlobalSecretKey::from_hex(hex).map(PyBlindedAttributeGlobalSecretKey)
}
fn __repr__(&self) -> String {
format!("BlindedAttributeGlobalSecretKey({})", self.as_hex())
}
fn __str__(&self) -> String {
self.as_hex()
}
fn __eq__(&self, other: &PyBlindedAttributeGlobalSecretKey) -> bool {
self.0 == other.0
}
}
#[derive(Copy, Clone, Eq, PartialEq, Debug, From, Into)]
#[pyclass(name = "BlindedGlobalKeys", from_py_object)]
pub struct PyBlindedGlobalKeys {
#[pyo3(get)]
pub pseudonym: PyBlindedPseudonymGlobalSecretKey,
#[pyo3(get)]
pub attribute: PyBlindedAttributeGlobalSecretKey,
}
#[pymethods]
impl PyBlindedGlobalKeys {
#[new]
fn new(
pseudonym: PyBlindedPseudonymGlobalSecretKey,
attribute: PyBlindedAttributeGlobalSecretKey,
) -> Self {
PyBlindedGlobalKeys {
pseudonym,
attribute,
}
}
fn __repr__(&self) -> String {
format!(
"BlindedGlobalKeys(pseudonym={}, attribute={})",
self.pseudonym.as_hex(),
self.attribute.as_hex()
)
}
fn __eq__(&self, other: &PyBlindedGlobalKeys) -> bool {
self.pseudonym == other.pseudonym && self.attribute == other.attribute
}
}
#[pyfunction]
#[pyo3(name = "make_blinded_pseudonym_global_secret_key")]
pub fn py_make_blinded_pseudonym_global_secret_key(
global_secret_key: &PyPseudonymGlobalSecretKey,
blinding_factors: Vec<PyBlindingFactor>,
) -> PyResult<PyBlindedPseudonymGlobalSecretKey> {
let bs: Vec<BlindingFactor> = blinding_factors
.into_iter()
.map(|x| BlindingFactor(x.0 .0))
.collect();
let result = make_blinded_pseudonym_global_secret_key(
&PseudonymGlobalSecretKey::from(global_secret_key.0 .0),
&bs,
)
.ok_or_else(|| pyo3::exceptions::PyValueError::new_err("Product of blinding factors is 1"))?;
Ok(PyBlindedPseudonymGlobalSecretKey(result))
}
#[pyfunction]
#[pyo3(name = "make_blinded_attribute_global_secret_key")]
pub fn py_make_blinded_attribute_global_secret_key(
global_secret_key: &PyAttributeGlobalSecretKey,
blinding_factors: Vec<PyBlindingFactor>,
) -> PyResult<PyBlindedAttributeGlobalSecretKey> {
let bs: Vec<BlindingFactor> = blinding_factors
.into_iter()
.map(|x| BlindingFactor(x.0 .0))
.collect();
let result = make_blinded_attribute_global_secret_key(
&AttributeGlobalSecretKey::from(global_secret_key.0 .0),
&bs,
)
.ok_or_else(|| pyo3::exceptions::PyValueError::new_err("Product of blinding factors is 1"))?;
Ok(PyBlindedAttributeGlobalSecretKey(result))
}
#[pyfunction]
#[pyo3(name = "make_blinded_global_keys")]
pub fn py_make_blinded_global_keys(
global_secret_keys: &PyGlobalSecretKeys,
blinding_factors: Vec<PyBlindingFactor>,
) -> PyResult<PyBlindedGlobalKeys> {
let bs: Vec<BlindingFactor> = blinding_factors
.into_iter()
.map(|x| BlindingFactor(x.0 .0))
.collect();
let result = make_blinded_global_keys(
&PseudonymGlobalSecretKey::from(global_secret_keys.pseudonym.0 .0),
&AttributeGlobalSecretKey::from(global_secret_keys.attribute.0 .0),
&bs,
)
.ok_or_else(|| pyo3::exceptions::PyValueError::new_err("Product of blinding factors is 1"))?;
Ok(PyBlindedGlobalKeys {
pseudonym: PyBlindedPseudonymGlobalSecretKey(result.pseudonym),
attribute: PyBlindedAttributeGlobalSecretKey(result.attribute),
})
}
pub fn register(m: &Bound<'_, PyModule>) -> PyResult<()> {
m.add_class::<PyBlindingFactor>()?;
m.add_class::<PyBlindedPseudonymGlobalSecretKey>()?;
m.add_class::<PyBlindedAttributeGlobalSecretKey>()?;
m.add_class::<PyBlindedGlobalKeys>()?;
m.add_function(wrap_pyfunction!(
py_make_blinded_pseudonym_global_secret_key,
m
)?)?;
m.add_function(wrap_pyfunction!(
py_make_blinded_attribute_global_secret_key,
m
)?)?;
m.add_function(wrap_pyfunction!(py_make_blinded_global_keys, m)?)?;
Ok(())
}