Skip to content

Commit

Permalink
Start tests
Browse files Browse the repository at this point in the history
  • Loading branch information
DarkaMaul committed Oct 2, 2024
1 parent 64d1d43 commit e6d9682
Show file tree
Hide file tree
Showing 8 changed files with 142 additions and 25 deletions.
41 changes: 26 additions & 15 deletions rust/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,21 +32,24 @@ impl TimeStampReq {
}

#[getter]
fn nonce<'p>(&self, py: pyo3::Python<'p>) -> PyResult<pyo3::Bound<'p, pyo3::PyAny>> {
fn nonce<'p>(&self, py: pyo3::Python<'p>) -> PyResult<Option<PyObject>> {
match self.raw.borrow_dependent().nonce {
Some(nonce) => {
let py_nonce = crate::util::big_asn1_uint_to_py(py, nonce)?;
Ok(py_nonce)
Ok(Some(py_nonce.into_py(py)))
}
None => todo!(),
None => Ok(None),
}
}

#[getter]
fn policy<'p>(&self, py: pyo3::Python<'p>) -> pyo3::PyResult<pyo3::Bound<'p, pyo3::PyAny>> {
fn policy<'p>(&self, py: pyo3::Python<'p>) -> pyo3::PyResult<Option<PyObject>> {
match &self.raw.borrow_dependent().req_policy {
Some(req_policy) => crate::util::oid_to_py_oid(py, &req_policy),
None => todo!(),
Some(req_policy) => {
let py_oid = crate::util::oid_to_py_oid(py, &req_policy)?;
Ok(Some(py_oid.into_py(py)))
},
None => Ok(None),
}
}

Expand All @@ -59,9 +62,14 @@ impl TimeStampReq {
fn message_imprint(&self, py: pyo3::Python<'_>) -> PyResult<PyMessageImprint> {
Ok(PyMessageImprint {
contents: OwnedMessageImprint::try_new(self.raw.borrow_owner().clone_ref(py), |v| {
RawMessageImprint::parse_data(v.as_bytes(py))
})
.map_err(|_| PyValueError::new_err("invalid message imprint"))?,

let req = asn1::parse_single::<RawTimeStampReq>(v.as_bytes(py))
.map_err(|e| PyValueError::new_err(format!("invalid message imprint: {:?}", e)));
match req {
Ok(res) => Ok(res.message_imprint),
Err(_) => Err(PyValueError::new_err("Unable to retrieve message imprint"))
}
}).map_err(|e| PyValueError::new_err(format!("invalid message imprint: {:?}", e)))?,
})
}

Expand Down Expand Up @@ -371,10 +379,13 @@ impl PyTSTInfo {
}

#[getter]
fn policy<'p>(&self, py: pyo3::Python<'p>) -> pyo3::PyResult<pyo3::Bound<'p, pyo3::PyAny>> {
fn policy<'p>(&self, py: pyo3::Python<'p>) -> pyo3::PyResult<Option<PyObject>> {
match &self.raw.borrow_dependent().policy {
Some(req_policy) => crate::util::oid_to_py_oid(py, &req_policy),
None => todo!(),
Some(req_policy) => {
let py_oid = crate::util::oid_to_py_oid(py, &req_policy)?;
Ok(Some(py_oid.into_py(py)))
},
None => Ok(None),
}
}

Expand Down Expand Up @@ -418,13 +429,13 @@ impl PyTSTInfo {
}

#[getter]
fn nonce<'p>(&self, py: Python<'p>) -> PyResult<pyo3::Bound<'p, pyo3::PyAny>> {
fn nonce<'p>(&self, py: Python<'p>) -> PyResult<Option<PyObject>> {
match self.raw.borrow_dependent().nonce {
Some(nonce) => {
let py_nonce = crate::util::big_asn1_uint_to_py(py, nonce)?;
Ok(py_nonce)
Ok(Some(py_nonce.into_py(py)))
}
None => todo!(),
None => Ok(None),
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/sigstore_tsp/_rust/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ class PyTSTInfo: ...

class Accuracy: ...

class SignerInfo: ...

def create_timestamp_request(
data: bytes,
) -> TimeStampRequest: ...
Expand Down
6 changes: 0 additions & 6 deletions src/sigstore_tsp/impl.py

This file was deleted.

13 changes: 13 additions & 0 deletions src/sigstore_tsp/tsp.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,5 +197,18 @@ def certificates(self) -> set[bytes]:
Warning: they are returned as a byte array and should be loaded.
"""

@property
@abc.abstractmethod
def signer_infos(self) -> set[SignerInfo]:
"""Returns the signers infos."""

SignedData.register(_rust.SignedData)


class SignerInfo(metaclass=abc.ABCMeta):
@property
@abc.abstractmethod
def version(self) -> int:
"""Returns the version."""

SignerInfo.register(_rust.SignerInfo)
19 changes: 15 additions & 4 deletions src/sigstore_tsp/verify.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,22 @@ def _verify_tsr_with_chains(tsp_response: TimeStampResponse, opts: VerifyOpts) -
return False

signed_data = tsp_response.signed_data
if not signed_data.certificates and opts.tsa_certificate:
# TODO(dm) I can't assign here because that's read only
signed_data.certificates = opts.tsa_certificate

# TODO(dm)
verification_certificate = []
if signed_data.certificates:
verification_certificate = signed_data.certificates
elif not signed_data.certificates and opts.tsa_certificate:
verification_certificate = [ opts.tsa_certificate ]

# https://github.com/digitorus/pkcs7/blob/3a137a8743524b3683ca4e11608d0dde37caee99/verify.go#L74
if len(signed_data.signer_infos) == 0:
# No signer presents
return False

# TODO(dm): Here we would need to check the pkcs7 signer info
# and verify the signature. Instead of implementing it here,
# we should probably leverage some library that already does that.

return True


Expand Down
Binary file added test/fixtures/response.tsr
Binary file not shown.
35 changes: 35 additions & 0 deletions test/fixtures/ts_chain.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
-----BEGIN CERTIFICATE-----
MIIBzTCCAXKgAwIBAgIUB1fm1kzgFYdI15DCbcR2znmNvX4wCgYIKoZIzj0EAwIw
MDEOMAwGA1UEChMFbG9jYWwxHjAcBgNVBAMTFVRlc3QgVFNBIEludGVybWVkaWF0
ZTAeFw0yNDA5MjYxNTA0MzFaFw0zMzA5MjYxNTA3MzFaMDAxDjAMBgNVBAoTBWxv
Y2FsMR4wHAYDVQQDExVUZXN0IFRTQSBUaW1lc3RhbXBpbmcwWTATBgcqhkjOPQIB
BggqhkjOPQMBBwNCAAQJLOx1er3OYoh8ye10R33JuC36SdbPUeX/0OrzIfPLIzNt
318lOG4/M88AcQUUP8/cfvUYDfYvz13Y/BKqyJqgo2owaDAOBgNVHQ8BAf8EBAMC
B4AwHQYDVR0OBBYEFDR3RW7sspK5nJCgMYmaLjLzQgsGMB8GA1UdIwQYMBaAFALx
2SsaTew5WmKDNUC5W7rBxmnbMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMIMAoGCCqG
SM49BAMCA0kAMEYCIQCf9psWVtVrxe4x9EhAqHB1p6HAbOO1T7eFAxkzUedOpgIh
APpWUuquAsYBmwKOYSf/X4WconKtNy0tm44N3WhiH5rz
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIB0jCCAXigAwIBAgIUHol7Z0HtRLCFwDD2ymKu/VcyZ9UwCgYIKoZIzj0EAwIw
KDEOMAwGA1UEChMFbG9jYWwxFjAUBgNVBAMTDVRlc3QgVFNBIFJvb3QwHhcNMjQw
OTI2MTUwMjMxWhcNMzQwOTI2MTUwNzMxWjAwMQ4wDAYDVQQKEwVsb2NhbDEeMBwG
A1UEAxMVVGVzdCBUU0EgSW50ZXJtZWRpYXRlMFkwEwYHKoZIzj0CAQYIKoZIzj0D
AQcDQgAEGzVCgkzDQkMqxRlXPXADxFS7/e8u3/j/PI4xkOZtdN6/9PPPdy5IimK/
OoQq8sNmMfb0CriyIYnKoNwJ1dUdHKN4MHYwDgYDVR0PAQH/BAQDAgEGMBMGA1Ud
JQQMMAoGCCsGAQUFBwMIMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFALx2Ssa
Tew5WmKDNUC5W7rBxmnbMB8GA1UdIwQYMBaAFCnKpTwP0pqRflw/vUbiZHjEZc5M
MAoGCCqGSM49BAMCA0gAMEUCIQC9S7bLB8bi4cjMEaX4ZAooXT7vNbAvfseaWUW8
dv8RQwIgZgQF1amkhMU1H8aXprou7vYH5rbmzuElAyS6TA//kzs=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIBkzCCATqgAwIBAgIUGpdpdZ+1u5mA3jRd/m7vmPQWyWMwCgYIKoZIzj0EAwIw
KDEOMAwGA1UEChMFbG9jYWwxFjAUBgNVBAMTDVRlc3QgVFNBIFJvb3QwHhcNMjQw
OTI2MTUwMjMxWhcNMzQwOTI2MTUwNzMxWjAoMQ4wDAYDVQQKEwVsb2NhbDEWMBQG
A1UEAxMNVGVzdCBUU0EgUm9vdDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABIA1
o2pTsSxfoQRya3E+GAM7a9cOrvhG5mkpEsQaO+7CL3VyIpszValjuqYwDpEaXei9
Ko9P5iEoru0uYEmoT7mjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTAD
AQH/MB0GA1UdDgQWBBQpyqU8D9KakX5cP71G4mR4xGXOTDAKBggqhkjOPQQDAgNH
ADBEAiAggb/CCtUjIxxuoffQ85ugdylmO9xYgzhjJqcjiYodQwIgT8h6J4Ace2on
JkTMML0sqzXiqoUfwMzWJlBhKC7y12Y=
-----END CERTIFICATE-----
51 changes: 51 additions & 0 deletions test/test_verify.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
from pathlib import Path
import cryptography.x509

from sigstore_tsp.base import TimestampRequestBuilder, decode_timestamp_response
from sigstore_tsp.verify import verify_timestamp_response, VerifyOpts, create_verify_opts



_HERE = Path(__file__).parent.resolve()
_FIXTURE = _HERE / "fixtures"

def test_create_verify_opts():
request = TimestampRequestBuilder().data(b"hello").build()

certificates = cryptography.x509.load_pem_x509_certificates(
(_FIXTURE / "ts_chain.pem").read_bytes()
)

verify_opts = create_verify_opts(
request,
tsa_certifiate=certificates[0],
common_name=certificates[0].subject.rfc4514_string(),
root_certificates=[certificates[-1]],
intermediates=certificates[1:-1],
)

assert verify_opts.nonce == request.nonce
assert verify_opts.policy_id == request.policy
assert verify_opts.tsa_certificate == certificates[0]


def test_verify():

request = TimestampRequestBuilder().data(b"hello").build()
response = (_FIXTURE / "response.tsr").read_bytes()
certificates = cryptography.x509.load_pem_x509_certificates(
(_FIXTURE / "ts_chain.pem").read_bytes()
)

verify_opts = create_verify_opts(
request,
tsa_certifiate=certificates[0],
common_name=certificates[0].subject.rfc4514_string(),
root_certificates=[certificates[-1]],
)

verify_timestamp_response(
timestamp_response=decode_timestamp_response(response),
hashed_message=request.message_imprint.message,
verify_opts=verify_opts,
)

0 comments on commit e6d9682

Please sign in to comment.