use crate::client::{decrypt, encrypt};
use crate::data::long::{
LongAttribute, LongEncryptedAttribute, LongEncryptedPseudonym, LongPseudonym,
};
use crate::data::py::simple::{
PyAttribute, PyEncryptedAttribute, PyEncryptedPseudonym, PyPseudonym,
};
use crate::data::simple::{Attribute, EncryptedAttribute, EncryptedPseudonym, Pseudonym};
use crate::keys::py::types::{
PyAttributeSessionPublicKey, PyAttributeSessionSecretKey, PyPseudonymSessionPublicKey,
PyPseudonymSessionSecretKey,
};
use crate::keys::types::{
AttributeSessionPublicKey, AttributeSessionSecretKey, PseudonymSessionPublicKey,
PseudonymSessionSecretKey,
};
use derive_more::{Deref, From};
use pyo3::prelude::*;
use pyo3::types::{PyAny, PyBytes};
use pyo3::Py;
#[pyclass(name = "LongPseudonym", from_py_object)]
#[derive(Clone, Eq, PartialEq, Debug, From, Deref)]
pub struct PyLongPseudonym(pub(crate) LongPseudonym);
#[pymethods]
impl PyLongPseudonym {
#[new]
fn new(pseudonyms: Vec<PyPseudonym>) -> Self {
let rust_pseudonyms: Vec<Pseudonym> = pseudonyms.into_iter().map(|p| p.0).collect();
Self(LongPseudonym(rust_pseudonyms))
}
#[staticmethod]
#[pyo3(name = "from_string_padded")]
fn from_string_padded(text: &str) -> Self {
Self(LongPseudonym::from_string_padded(text))
}
#[staticmethod]
#[pyo3(name = "from_bytes_padded")]
fn from_bytes_padded(data: &[u8]) -> Self {
Self(LongPseudonym::from_bytes_padded(data))
}
#[pyo3(name = "to_string_padded")]
fn to_string_padded(&self) -> PyResult<String> {
self.0
.to_string_padded()
.map_err(|e| pyo3::exceptions::PyValueError::new_err(format!("Decoding failed: {e}")))
}
#[pyo3(name = "to_bytes_padded")]
fn to_bytes_padded(&self, py: Python) -> PyResult<Py<PyAny>> {
let result = self.0.to_bytes_padded().map_err(|e| {
pyo3::exceptions::PyValueError::new_err(format!("Decoding failed: {e}"))
})?;
Ok(PyBytes::new(py, &result).into())
}
#[pyo3(name = "pad_to")]
fn pad_to(&self, target_blocks: usize) -> PyResult<Self> {
self.0
.pad_to(target_blocks)
.map(Self)
.map_err(|e| pyo3::exceptions::PyValueError::new_err(format!("Padding failed: {e}")))
}
#[pyo3(name = "pseudonyms")]
fn pseudonyms(&self) -> Vec<PyPseudonym> {
self.0 .0.iter().map(|p| PyPseudonym(*p)).collect()
}
fn __len__(&self) -> usize {
self.0 .0.len()
}
fn __repr__(&self) -> String {
format!("LongPseudonym({} blocks)", self.0 .0.len())
}
fn __eq__(&self, other: &PyLongPseudonym) -> bool {
self.0 == other.0
}
}
#[pyclass(name = "LongAttribute", from_py_object)]
#[derive(Clone, Eq, PartialEq, Debug, From, Deref)]
pub struct PyLongAttribute(pub(crate) LongAttribute);
#[pymethods]
impl PyLongAttribute {
#[new]
fn new(attributes: Vec<PyAttribute>) -> Self {
let rust_attributes: Vec<Attribute> = attributes.into_iter().map(|a| a.0).collect();
Self(LongAttribute(rust_attributes))
}
#[staticmethod]
#[pyo3(name = "from_string_padded")]
fn from_string_padded(text: &str) -> Self {
Self(LongAttribute::from_string_padded(text))
}
#[staticmethod]
#[pyo3(name = "from_bytes_padded")]
fn from_bytes_padded(data: &[u8]) -> Self {
Self(LongAttribute::from_bytes_padded(data))
}
#[pyo3(name = "to_string_padded")]
fn to_string_padded(&self) -> PyResult<String> {
self.0
.to_string_padded()
.map_err(|e| pyo3::exceptions::PyValueError::new_err(format!("Decoding failed: {e}")))
}
#[pyo3(name = "to_bytes_padded")]
fn to_bytes_padded(&self, py: Python) -> PyResult<Py<PyAny>> {
let result = self.0.to_bytes_padded().map_err(|e| {
pyo3::exceptions::PyValueError::new_err(format!("Decoding failed: {e}"))
})?;
Ok(PyBytes::new(py, &result).into())
}
#[pyo3(name = "pad_to")]
fn pad_to(&self, target_blocks: usize) -> PyResult<Self> {
self.0
.pad_to(target_blocks)
.map(Self)
.map_err(|e| pyo3::exceptions::PyValueError::new_err(format!("Padding failed: {e}")))
}
#[pyo3(name = "attributes")]
fn attributes(&self) -> Vec<PyAttribute> {
self.0 .0.iter().map(|a| PyAttribute(*a)).collect()
}
fn __len__(&self) -> usize {
self.0 .0.len()
}
fn __repr__(&self) -> String {
format!("LongAttribute({} blocks)", self.0 .0.len())
}
fn __eq__(&self, other: &PyLongAttribute) -> bool {
self.0 == other.0
}
}
#[pyclass(name = "LongEncryptedPseudonym", from_py_object)]
#[derive(Clone, Eq, PartialEq, Debug, From, Deref)]
pub struct PyLongEncryptedPseudonym(pub(crate) LongEncryptedPseudonym);
#[pymethods]
impl PyLongEncryptedPseudonym {
#[new]
fn new(encrypted_pseudonyms: Vec<PyEncryptedPseudonym>) -> Self {
let rust_enc_pseudonyms: Vec<EncryptedPseudonym> =
encrypted_pseudonyms.into_iter().map(|p| p.0).collect();
Self(LongEncryptedPseudonym(rust_enc_pseudonyms))
}
#[pyo3(name = "serialize")]
fn serialize(&self) -> String {
self.0.serialize()
}
#[staticmethod]
#[pyo3(name = "deserialize")]
fn deserialize(s: &str) -> PyResult<Self> {
LongEncryptedPseudonym::deserialize(s)
.map(Self)
.map_err(|e| {
pyo3::exceptions::PyValueError::new_err(format!("Deserialization failed: {e}"))
})
}
#[pyo3(name = "encrypted_pseudonyms")]
fn encrypted_pseudonyms(&self) -> Vec<PyEncryptedPseudonym> {
self.0 .0.iter().map(|p| PyEncryptedPseudonym(*p)).collect()
}
fn __len__(&self) -> usize {
self.0 .0.len()
}
fn __repr__(&self) -> String {
format!("LongEncryptedPseudonym({} blocks)", self.0 .0.len())
}
fn __eq__(&self, other: &PyLongEncryptedPseudonym) -> bool {
self.0 == other.0
}
}
#[pyclass(name = "LongEncryptedAttribute", from_py_object)]
#[derive(Clone, Eq, PartialEq, Debug, From, Deref)]
pub struct PyLongEncryptedAttribute(pub(crate) LongEncryptedAttribute);
#[pymethods]
impl PyLongEncryptedAttribute {
#[new]
fn new(encrypted_attributes: Vec<PyEncryptedAttribute>) -> Self {
let rust_enc_attributes: Vec<EncryptedAttribute> =
encrypted_attributes.into_iter().map(|a| a.0).collect();
Self(LongEncryptedAttribute(rust_enc_attributes))
}
#[pyo3(name = "serialize")]
fn serialize(&self) -> String {
self.0.serialize()
}
#[staticmethod]
#[pyo3(name = "deserialize")]
fn deserialize(s: &str) -> PyResult<Self> {
LongEncryptedAttribute::deserialize(s)
.map(Self)
.map_err(|e| {
pyo3::exceptions::PyValueError::new_err(format!("Deserialization failed: {e}"))
})
}
#[pyo3(name = "encrypted_attributes")]
fn encrypted_attributes(&self) -> Vec<PyEncryptedAttribute> {
self.0 .0.iter().map(|a| PyEncryptedAttribute(*a)).collect()
}
fn __len__(&self) -> usize {
self.0 .0.len()
}
fn __repr__(&self) -> String {
format!("LongEncryptedAttribute({} blocks)", self.0 .0.len())
}
fn __eq__(&self, other: &PyLongEncryptedAttribute) -> bool {
self.0 == other.0
}
}
#[pyfunction]
#[pyo3(name = "encrypt_long_pseudonym")]
pub fn py_encrypt_long_pseudonym(
message: &PyLongPseudonym,
public_key: &PyPseudonymSessionPublicKey,
) -> PyLongEncryptedPseudonym {
let mut rng = rand::rng();
PyLongEncryptedPseudonym(encrypt(
&message.0,
&PseudonymSessionPublicKey::from(public_key.0 .0),
&mut rng,
))
}
#[cfg(feature = "elgamal3")]
#[pyfunction]
#[pyo3(name = "decrypt_long_pseudonym")]
pub fn py_decrypt_long_pseudonym(
encrypted: &PyLongEncryptedPseudonym,
secret_key: &PyPseudonymSessionSecretKey,
) -> Option<PyLongPseudonym> {
decrypt(
&encrypted.0,
&PseudonymSessionSecretKey::from(secret_key.0 .0),
)
.map(PyLongPseudonym)
}
#[cfg(not(feature = "elgamal3"))]
#[pyfunction]
#[pyo3(name = "decrypt_long_pseudonym")]
pub fn py_decrypt_long_pseudonym(
encrypted: &PyLongEncryptedPseudonym,
secret_key: &PyPseudonymSessionSecretKey,
) -> PyLongPseudonym {
PyLongPseudonym(decrypt(
&encrypted.0,
&PseudonymSessionSecretKey::from(secret_key.0 .0),
))
}
#[pyfunction]
#[pyo3(name = "encrypt_long_attribute")]
pub fn py_encrypt_long_attribute(
message: &PyLongAttribute,
public_key: &PyAttributeSessionPublicKey,
) -> PyLongEncryptedAttribute {
let mut rng = rand::rng();
PyLongEncryptedAttribute(encrypt(
&message.0,
&AttributeSessionPublicKey::from(public_key.0 .0),
&mut rng,
))
}
#[cfg(feature = "elgamal3")]
#[pyfunction]
#[pyo3(name = "decrypt_long_attribute")]
pub fn py_decrypt_long_attribute(
encrypted: &PyLongEncryptedAttribute,
secret_key: &PyAttributeSessionSecretKey,
) -> Option<PyLongAttribute> {
decrypt(
&encrypted.0,
&AttributeSessionSecretKey::from(secret_key.0 .0),
)
.map(PyLongAttribute)
}
#[cfg(not(feature = "elgamal3"))]
#[pyfunction]
#[pyo3(name = "decrypt_long_attribute")]
pub fn py_decrypt_long_attribute(
encrypted: &PyLongEncryptedAttribute,
secret_key: &PyAttributeSessionSecretKey,
) -> PyLongAttribute {
PyLongAttribute(decrypt(
&encrypted.0,
&AttributeSessionSecretKey::from(secret_key.0 .0),
))
}
pub fn register(m: &Bound<'_, PyModule>) -> PyResult<()> {
m.add_class::<PyLongPseudonym>()?;
m.add_class::<PyLongAttribute>()?;
m.add_class::<PyLongEncryptedPseudonym>()?;
m.add_class::<PyLongEncryptedAttribute>()?;
Ok(())
}