#![allow(rustdoc::invalid_rust_codeblocks)]
use pyo3::prelude::*;
pub mod certificate;
pub mod crypto;
pub mod crypto_keys;
pub mod decoder;
pub mod encoder;
pub mod error;
pub mod ext_builders;
pub mod otp;
pub mod types;
pub mod x509_verification;
pub use certificate::*;
pub use decoder::*;
pub use encoder::*;
pub use error::*;
pub use types::*;
pub(crate) use synta_python_common::install_submodule;
#[pyclass(name = "Encoding")]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PyEncoding {
DER,
BER,
CER,
}
impl From<PyEncoding> for synta::Encoding {
fn from(enc: PyEncoding) -> Self {
match enc {
PyEncoding::DER => synta::Encoding::Der,
PyEncoding::BER => synta::Encoding::Ber,
PyEncoding::CER => synta::Encoding::Cer,
}
}
}
impl From<synta::Encoding> for PyEncoding {
fn from(enc: synta::Encoding) -> Self {
match enc {
synta::Encoding::Der => PyEncoding::DER,
synta::Encoding::Ber => PyEncoding::BER,
synta::Encoding::Cer => PyEncoding::CER,
}
}
}
#[pymodule]
fn _synta(py: Python, m: &Bound<'_, PyModule>) -> PyResult<()> {
m.add_class::<PyEncoding>()?;
m.add("SyntaError", py.get_type::<SyntaError>())?;
m.add_class::<PyDecoder>()?;
m.add_class::<PyEncoder>()?;
m.add_class::<PyInteger>()?;
m.add_class::<PyOctetString>()?;
m.add_class::<PyBitString>()?;
m.add_class::<PyBoolean>()?;
m.add_class::<PyReal>()?;
m.add_class::<PyUtcTime>()?;
m.add_class::<PyGeneralizedTime>()?;
m.add_class::<PyNull>()?;
m.add_class::<PyUtf8String>()?;
m.add_class::<PyPrintableString>()?;
m.add_class::<PyIA5String>()?;
m.add_class::<PyNumericString>()?;
m.add_class::<PyTeletexString>()?;
m.add_class::<PyVisibleString>()?;
m.add_class::<PyGeneralString>()?;
m.add_class::<PyUniversalString>()?;
m.add_class::<PyBmpString>()?;
m.add_class::<PyTaggedElement>()?;
m.add_class::<PyRawElement>()?;
certificate::register_module(m)?;
m.add_function(wrap_pyfunction!(pem_to_der, m)?)?;
m.add_function(wrap_pyfunction!(der_to_pem, m)?)?;
m.add_function(wrap_pyfunction!(parse_general_names, m)?)?;
m.add_function(wrap_pyfunction!(parse_name_attrs, m)?)?;
m.add_function(wrap_pyfunction!(encode_extended_key_usage, m)?)?;
m.add_function(wrap_pyfunction!(encode_subject_alt_names, m)?)?;
m.add_function(wrap_pyfunction!(name_der_equal, m)?)?;
m.add_function(wrap_pyfunction!(digest, m)?)?;
m.add_class::<crypto_keys::PyPublicKey>()?;
m.add_class::<crypto_keys::PyPrivateKey>()?;
crypto::register_crypto_module(m)?;
ext_builders::register_ext_module(m)?;
x509_verification::register_x509_module(m)?;
m.add("__version__", env!("CARGO_PKG_VERSION"))?;
Ok(())
}
#[pyfunction]
fn parse_general_names<'py>(
py: Python<'py>,
san_der: &[u8],
) -> PyResult<Bound<'py, pyo3::types::PyList>> {
use pyo3::types::{PyBytes, PyList, PyTuple};
let list = PyList::empty(py);
for (tag_num, content) in synta_certificate::parse_general_names(san_der) {
let tuple = PyTuple::new(
py,
[
tag_num.into_pyobject(py)?.into_any(),
PyBytes::new(py, &content).into_any(),
],
)?;
list.append(tuple)?;
}
Ok(list)
}
#[pyfunction]
fn parse_name_attrs<'py>(
py: Python<'py>,
name_der: &[u8],
) -> PyResult<Bound<'py, pyo3::types::PyList>> {
use pyo3::types::{PyList, PyTuple};
let attrs = synta_certificate::name::parse_name_attrs(name_der);
let list = PyList::empty(py);
for (oid, value) in attrs {
let tuple = PyTuple::new(
py,
[
oid.into_pyobject(py)?.into_any(),
value.into_pyobject(py)?.into_any(),
],
)?;
list.append(tuple)?;
}
Ok(list)
}
#[pyfunction]
fn der_to_pem<'py>(py: Python<'py>, der: &[u8], label: &str) -> Bound<'py, pyo3::types::PyBytes> {
pyo3::types::PyBytes::new(py, &synta_certificate::der_to_pem(label, der))
}
#[pyfunction]
fn pem_to_der<'py>(
py: Python<'py>,
data: &[u8],
) -> PyResult<pyo3::Bound<'py, pyo3::types::PyList>> {
let blocks = synta_certificate::pem_blocks(data);
if blocks.is_empty() {
return Err(pyo3::exceptions::PyValueError::new_err(
"no PEM block found in input",
));
}
let list = pyo3::types::PyList::empty(py);
for (_, block) in &blocks {
list.append(pyo3::types::PyBytes::new(py, block))?;
}
Ok(list)
}
#[pyfunction]
fn digest<'py>(
py: Python<'py>,
algorithm: &str,
data: &[u8],
) -> PyResult<pyo3::Bound<'py, pyo3::types::PyBytes>> {
use synta_certificate::{default_data_hasher, DataHasher};
let d = default_data_hasher()
.hash_data(algorithm, data)
.map_err(|e| pyo3::exceptions::PyValueError::new_err(format!("{e}")))?;
Ok(pyo3::types::PyBytes::new(py, &d))
}