diff --git a/src/cryptography/hazmat/bindings/_rust/asn1.pyi b/src/cryptography/hazmat/bindings/_rust/asn1.pyi index 35652c6ada1c..3b5f208ecf09 100644 --- a/src/cryptography/hazmat/bindings/_rust/asn1.pyi +++ b/src/cryptography/hazmat/bindings/_rust/asn1.pyi @@ -2,13 +2,6 @@ # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. -class TestCertificate: - not_after_tag: int - not_before_tag: int - issuer_value_tags: list[int] - subject_value_tags: list[int] - def decode_dss_signature(signature: bytes) -> tuple[int, int]: ... def encode_dss_signature(r: int, s: int) -> bytes: ... def parse_spki_for_data(data: bytes) -> bytes: ... -def test_parse_certificate(data: bytes) -> TestCertificate: ... diff --git a/src/cryptography/hazmat/bindings/_rust/test_support.pyi b/src/cryptography/hazmat/bindings/_rust/test_support.pyi new file mode 100644 index 000000000000..020c5951d2ab --- /dev/null +++ b/src/cryptography/hazmat/bindings/_rust/test_support.pyi @@ -0,0 +1,11 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +class TestCertificate: + not_after_tag: int + not_before_tag: int + issuer_value_tags: list[int] + subject_value_tags: list[int] + +def test_parse_certificate(data: bytes) -> TestCertificate: ... diff --git a/src/rust/src/asn1.rs b/src/rust/src/asn1.rs index c306104b8585..366fc69eacd6 100644 --- a/src/rust/src/asn1.rs +++ b/src/rust/src/asn1.rs @@ -2,10 +2,7 @@ // 2.0, and the BSD License. See the LICENSE file in the root of this repository // for complete details. -use asn1::SimpleAsn1Readable; -use cryptography_x509::certificate::Certificate; -use cryptography_x509::common::{DssSignature, SubjectPublicKeyInfo, Time}; -use cryptography_x509::name::Name; +use cryptography_x509::common::{DssSignature, SubjectPublicKeyInfo}; use pyo3::pybacked::PyBackedBytes; use pyo3::types::IntoPyDict; use pyo3::types::PyAnyMethods; @@ -133,53 +130,9 @@ fn encode_dss_signature<'p>( Ok(pyo3::types::PyBytes::new_bound(py, &result)) } -#[pyo3::pyclass(frozen, module = "cryptography.hazmat.bindings._rust.asn1")] -struct TestCertificate { - #[pyo3(get)] - not_before_tag: u8, - #[pyo3(get)] - not_after_tag: u8, - #[pyo3(get)] - issuer_value_tags: Vec, - #[pyo3(get)] - subject_value_tags: Vec, -} - -fn parse_name_value_tags(rdns: &Name<'_>) -> Vec { - let mut tags = vec![]; - for rdn in rdns.unwrap_read().clone() { - let mut attributes = rdn.collect::>(); - assert_eq!(attributes.len(), 1); - - tags.push(attributes.pop().unwrap().value.tag().as_u8().unwrap()); - } - tags -} - -fn time_tag(t: &Time) -> u8 { - match t { - Time::UtcTime(_) => asn1::UtcTime::TAG.as_u8().unwrap(), - Time::GeneralizedTime(_) => asn1::GeneralizedTime::TAG.as_u8().unwrap(), - } -} - -#[pyo3::pyfunction] -fn test_parse_certificate(data: &[u8]) -> Result { - let cert = asn1::parse_single::>(data)?; - - Ok(TestCertificate { - not_before_tag: time_tag(&cert.tbs_cert.validity.not_before), - not_after_tag: time_tag(&cert.tbs_cert.validity.not_after), - issuer_value_tags: parse_name_value_tags(&cert.tbs_cert.issuer), - subject_value_tags: parse_name_value_tags(&cert.tbs_cert.subject), - }) -} - #[pyo3::pymodule] #[pyo3(name = "asn1")] pub(crate) mod asn1_mod { #[pymodule_export] - use super::{ - decode_dss_signature, encode_dss_signature, parse_spki_for_data, test_parse_certificate, - }; + use super::{decode_dss_signature, encode_dss_signature, parse_spki_for_data}; } diff --git a/src/rust/src/lib.rs b/src/rust/src/lib.rs index 8f6ecc053fe5..cd7b99f1570a 100644 --- a/src/rust/src/lib.rs +++ b/src/rust/src/lib.rs @@ -21,6 +21,7 @@ pub(crate) mod oid; mod padding; mod pkcs12; mod pkcs7; +mod test_support; pub(crate) mod types; mod x509; @@ -106,6 +107,8 @@ mod _rust { use crate::pkcs12::pkcs12; #[pymodule_export] use crate::pkcs7::pkcs7_mod; + #[pymodule_export] + use crate::test_support::test_support; #[pyo3::pymodule] mod x509 { diff --git a/src/rust/src/test_support.rs b/src/rust/src/test_support.rs new file mode 100644 index 000000000000..5b42fec3b304 --- /dev/null +++ b/src/rust/src/test_support.rs @@ -0,0 +1,57 @@ +// This file is dual licensed under the terms of the Apache License, Version +// 2.0, and the BSD License. See the LICENSE file in the root of this repository +// for complete details. + +use crate::error::CryptographyResult; +use asn1::SimpleAsn1Readable; +use cryptography_x509::certificate::Certificate; +use cryptography_x509::common::Time; +use cryptography_x509::name::Name; + +#[pyo3::pyclass(frozen, module = "cryptography.hazmat.bindings._rust.test_support")] +struct TestCertificate { + #[pyo3(get)] + not_before_tag: u8, + #[pyo3(get)] + not_after_tag: u8, + #[pyo3(get)] + issuer_value_tags: Vec, + #[pyo3(get)] + subject_value_tags: Vec, +} + +fn parse_name_value_tags(rdns: &Name<'_>) -> Vec { + let mut tags = vec![]; + for rdn in rdns.unwrap_read().clone() { + let mut attributes = rdn.collect::>(); + assert_eq!(attributes.len(), 1); + + tags.push(attributes.pop().unwrap().value.tag().as_u8().unwrap()); + } + tags +} + +fn time_tag(t: &Time) -> u8 { + match t { + Time::UtcTime(_) => asn1::UtcTime::TAG.as_u8().unwrap(), + Time::GeneralizedTime(_) => asn1::GeneralizedTime::TAG.as_u8().unwrap(), + } +} + +#[pyo3::pyfunction] +fn test_parse_certificate(data: &[u8]) -> CryptographyResult { + let cert = asn1::parse_single::>(data)?; + + Ok(TestCertificate { + not_before_tag: time_tag(&cert.tbs_cert.validity.not_before), + not_after_tag: time_tag(&cert.tbs_cert.validity.not_after), + issuer_value_tags: parse_name_value_tags(&cert.tbs_cert.issuer), + subject_value_tags: parse_name_value_tags(&cert.tbs_cert.subject), + }) +} + +#[pyo3::pymodule] +pub(crate) mod test_support { + #[pymodule_export] + use super::test_parse_certificate; +} diff --git a/tests/x509/test_x509.py b/tests/x509/test_x509.py index a4368833ca3f..91251d58c0a3 100644 --- a/tests/x509/test_x509.py +++ b/tests/x509/test_x509.py @@ -14,7 +14,7 @@ from cryptography import utils, x509 from cryptography.exceptions import InvalidSignature, UnsupportedAlgorithm -from cryptography.hazmat.bindings._rust import asn1 +from cryptography.hazmat.bindings._rust import test_support from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import ( dh, @@ -2429,7 +2429,7 @@ def test_build_cert_printable_string_country_name( cert = builder.sign(issuer_private_key, hashes.SHA256(), backend) - parsed = asn1.test_parse_certificate( + parsed = test_support.test_parse_certificate( cert.public_bytes(serialization.Encoding.DER) ) @@ -2615,7 +2615,7 @@ def test_extreme_times( not_valid_before=not_valid_before, not_valid_after=not_valid_after, ) - parsed = asn1.test_parse_certificate( + parsed = test_support.test_parse_certificate( cert.public_bytes(serialization.Encoding.DER) ) # UTC TIME @@ -3088,7 +3088,7 @@ def test_earliest_time(self, rsa_key_2048: rsa.RSAPrivateKey, backend): ) cert = cert_builder.sign(private_key, hashes.SHA256(), backend) _check_cert_times(cert, not_valid_before=time, not_valid_after=time) - parsed = asn1.test_parse_certificate( + parsed = test_support.test_parse_certificate( cert.public_bytes(serialization.Encoding.DER) ) # UTC TIME