Skip to content

Commit

Permalink
more tests for 100% python coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
nitneuqr committed Sep 9, 2024
1 parent e1c4620 commit d4e7741
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 6 deletions.
7 changes: 6 additions & 1 deletion src/cryptography/hazmat/primitives/serialization/pkcs7.py
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ def set_recipient(
raise TypeError("certificate must be a x509.Certificate")

if not isinstance(certificate.public_key(), rsa.RSAPublicKey):
raise TypeError("Only RSA keys are supported at this time.")
raise TypeError("Only RSA public keys are supported at this time.")

return PKCS7EnvelopeDecryptor(
_data=self._data,
Expand All @@ -320,6 +320,11 @@ def set_private_key(
if self._private_key is not None:
raise ValueError("private key may only be set once")

if not isinstance(private_key, rsa.RSAPrivateKey):
raise TypeError(
"Only RSA private keys are supported at this time."
)

return PKCS7EnvelopeDecryptor(
_data=self._data,
_recipient=self._recipient,
Expand Down
94 changes: 89 additions & 5 deletions tests/hazmat/primitives/test_pkcs7.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import email.parser
import os
import typing
from email.message import EmailMessage

import pytest

Expand Down Expand Up @@ -1087,6 +1088,12 @@ def test_set_data_twice(self, backend):
with pytest.raises(ValueError):
decryptor.set_data(b"test")

def test_set_recipient_twice(self, backend):
cert, _ = _load_rsa_cert_key()
decryptor = pkcs7.PKCS7EnvelopeDecryptor().set_recipient(cert)
with pytest.raises(ValueError):
decryptor.set_recipient(cert)

def test_unsupported_encryption(self, backend):
cert_non_rsa, _ = _load_cert_key()
with pytest.raises(TypeError):
Expand All @@ -1098,30 +1105,80 @@ def test_not_a_cert(self, backend):
b"notacert", # type: ignore[arg-type]
)

def test_decrypt_no_recipient(self, backend):
decryptor = pkcs7.PKCS7EnvelopeDecryptor().set_data(b"test")
def test_set_private_key_twice(self, backend):
_, private_key = _load_rsa_cert_key()
decryptor = pkcs7.PKCS7EnvelopeDecryptor().set_private_key(private_key)
with pytest.raises(ValueError):
decryptor.decrypt(serialization.Encoding.SMIME, [])
decryptor.set_private_key(private_key)

def test_not_a_pkey(self, backend):
with pytest.raises(TypeError):
pkcs7.PKCS7EnvelopeDecryptor().set_private_key(
b"notapkey", # type: ignore[arg-type]
)

def test_decrypt_no_data(self, backend):
cert, _ = _load_rsa_cert_key()
decryptor = pkcs7.PKCS7EnvelopeDecryptor().set_recipient(cert)
with pytest.raises(ValueError):
decryptor.decrypt(serialization.Encoding.SMIME, [])

def test_decrypt_invalid_options(self, backend):
def test_decrypt_no_recipient(self, backend):
decryptor = pkcs7.PKCS7EnvelopeDecryptor().set_data(b"test")
with pytest.raises(ValueError):
decryptor.decrypt(serialization.Encoding.SMIME, [])

def test_decrypt_no_private_key(self, backend):
cert, _ = _load_rsa_cert_key()
decryptor = (
pkcs7.PKCS7EnvelopeDecryptor()
.set_data(b"test")
.set_recipient(cert)
)
with pytest.raises(ValueError):
decryptor.decrypt(serialization.Encoding.SMIME, [])

@pytest.fixture
def decryptor(self, backend) -> pkcs7.PKCS7EnvelopeDecryptor:
cert, private_key = _load_rsa_cert_key()
return (
pkcs7.PKCS7EnvelopeDecryptor()
.set_data(b"test")
.set_recipient(cert)
.set_private_key(private_key)
)

def test_decrypt_invalid_options(
self, backend, decryptor: pkcs7.PKCS7EnvelopeDecryptor
):
with pytest.raises(ValueError):
decryptor.decrypt(
serialization.Encoding.SMIME,
[b"invalid"], # type: ignore[list-item]
)

def test_decrypt_invalid_encoding(
self, backend, decryptor: pkcs7.PKCS7EnvelopeDecryptor
):
with pytest.raises(ValueError):
decryptor.decrypt(serialization.Encoding.Raw, [])

@pytest.mark.parametrize(
"invalid_options",
[
[pkcs7.PKCS7Options.NoAttributes],
[pkcs7.PKCS7Options.NoCapabilities],
[pkcs7.PKCS7Options.NoCerts],
[pkcs7.PKCS7Options.DetachedSignature],
[pkcs7.PKCS7Options.Binary, pkcs7.PKCS7Options.Text],
],
)
def test_encrypt_invalid_encryption_options(
self, backend, invalid_options, decryptor: pkcs7.PKCS7EnvelopeDecryptor
):
with pytest.raises(ValueError):
decryptor.decrypt(serialization.Encoding.DER, invalid_options)

@pytest.mark.parametrize(
("encoding", "options"),
[
Expand All @@ -1134,7 +1191,6 @@ def test_decrypt_invalid_options(self, backend):
],
)
def test_smime_decrypt(self, backend, encoding, options):
"""Testing the round-trip of encrypting and decrypting data."""
# Encrypt some data
plain = b"hello world\n"
cert, private_key = _load_rsa_cert_key()
Expand All @@ -1154,6 +1210,23 @@ def test_smime_decrypt(self, backend, encoding, options):
decrypted = decryptor.decrypt(encoding, options)
assert decrypted == plain

def test_smime_decrypt_not_encrypted(self, backend):
# Create a plain email
email_message = EmailMessage()
email_message.set_content("hello world\n")

# Test decryption failure with plain email
cert, private_key = _load_rsa_cert_key()
decryptor = (
pkcs7.PKCS7EnvelopeDecryptor()
.set_data(email_message.as_bytes())
.set_recipient(cert)
.set_private_key(private_key)
)

with pytest.raises(ValueError):
decryptor.decrypt(serialization.Encoding.SMIME, [])


@pytest.mark.supported(
only_if=lambda backend: backend.pkcs7_supported(),
Expand Down Expand Up @@ -1253,3 +1326,14 @@ class TestPKCS7EnvelopeBuilderUnsupported:
def test_envelope_builder_unsupported(self, backend):
with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_PADDING):
pkcs7.PKCS7EnvelopeBuilder()


@pytest.mark.supported(
only_if=lambda backend: backend.pkcs7_supported()
and not backend.rsa_encryption_supported(padding.PKCS1v15()),
skip_message="Requires OpenSSL with no PKCS1 v1.5 padding support",
)
class TestPKCS7EnvelopeDecryptorUnsupported:
def test_envelope_builder_unsupported(self, backend):
with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_PADDING):
pkcs7.PKCS7EnvelopeDecryptor()

0 comments on commit d4e7741

Please sign in to comment.