Skip to content

Commit 95c4f68

Browse files
authored
PKCS7SignatureBuilder now supports three serializations (#5497)
* PKCS7SignatureBuilder now supports three serializations PEM, DER, and SMIME. SMIME embeds the S/MIME headers and has the detached signature concept. * thanks libre
1 parent 5edf5b8 commit 95c4f68

6 files changed

Lines changed: 95 additions & 52 deletions

File tree

docs/hazmat/primitives/asymmetric/serialization.rst

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -620,7 +620,7 @@ contain certificates, CRLs, and much more. PKCS7 files commonly have a ``p7b``,
620620
... ).add_signer(
621621
... cert, key, hashes.SHA256()
622622
... ).sign(
623-
... serialization.Encoding.PEM, options
623+
... serialization.Encoding.SMIME, options
624624
... )
625625
b'...'
626626

@@ -649,8 +649,9 @@ contain certificates, CRLs, and much more. PKCS7 files commonly have a ``p7b``,
649649

650650
.. method:: sign(encoding, options, backend=None)
651651

652-
:param encoding: :attr:`~cryptography.hazmat.primitives.serialization.Encoding.PEM`
653-
or :attr:`~cryptography.hazmat.primitives.serialization.Encoding.DER`.
652+
:param encoding: :attr:`~cryptography.hazmat.primitives.serialization.Encoding.PEM`,
653+
:attr:`~cryptography.hazmat.primitives.serialization.Encoding.DER`,
654+
or :attr:`~cryptography.hazmat.primitives.serialization.Encoding.SMIME`.
654655

655656
:param options: A list of
656657
:class:`~cryptography.hazmat.primitives.serialization.pkcs7.PKCS7Options`.
@@ -670,19 +671,19 @@ contain certificates, CRLs, and much more. PKCS7 files commonly have a ``p7b``,
670671

671672
The text option adds ``text/plain`` headers to an S/MIME message when
672673
serializing to
673-
:attr:`~cryptography.hazmat.primitives.serialization.Encoding.PEM`.
674+
:attr:`~cryptography.hazmat.primitives.serialization.Encoding.SMIME`.
674675
This option is disallowed with ``DER`` serialization.
675676

676677
.. attribute:: Binary
677678

678-
S/MIME signing normally converts line endings (LF to CRLF). When
679+
Signing normally converts line endings (LF to CRLF). When
679680
passing this option the data will not be converted.
680681

681682
.. attribute:: DetachedSignature
682683

683684
Don't embed the signed data within the ASN.1. When signing with
684-
:attr:`~cryptography.hazmat.primitives.serialization.Encoding.PEM` this
685-
also results in the data being added as clear text before the
685+
:attr:`~cryptography.hazmat.primitives.serialization.Encoding.SMIME`
686+
this also results in the data being added as clear text before the
686687
PEM encoded structure.
687688

688689
.. attribute:: NoCapabilities
@@ -891,6 +892,12 @@ Serialization Encodings
891892
The format used by elliptic curve point encodings. This is a binary
892893
format.
893894

895+
.. attribute:: SMIME
896+
897+
.. versionadded:: 3.2
898+
899+
An output format used for PKCS7. This is a text format.
900+
894901

895902
Serialization Encryption Types
896903
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

src/_cffi_src/openssl/pkcs7.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
PKCS7 *PKCS7_sign(X509 *, EVP_PKEY *, Cryptography_STACK_OF_X509 *,
6161
BIO *, int);
6262
int SMIME_write_PKCS7(BIO *, PKCS7 *, BIO *, int);
63+
int PEM_write_bio_PKCS7_stream(BIO *, PKCS7 *, BIO *, int);
6364
PKCS7_SIGNER_INFO *PKCS7_sign_add_signer(PKCS7 *, X509 *, EVP_PKEY *,
6465
const EVP_MD *, int);
6566
int PKCS7_final(PKCS7 *, BIO *, int);

src/cryptography/hazmat/backends/openssl/backend.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2735,11 +2735,17 @@ def pkcs7_sign(self, builder, encoding, options):
27352735
final_flags |= self._lib.PKCS7_BINARY
27362736

27372737
bio_out = self._create_mem_bio_gc()
2738-
if encoding is serialization.Encoding.PEM:
2738+
if encoding is serialization.Encoding.SMIME:
27392739
# This finalizes the structure
27402740
res = self._lib.SMIME_write_PKCS7(
27412741
bio_out, p7, bio.bio, final_flags
27422742
)
2743+
elif encoding is serialization.Encoding.PEM:
2744+
res = self._lib.PKCS7_final(p7, bio.bio, final_flags)
2745+
self.openssl_assert(res == 1)
2746+
res = self._lib.PEM_write_bio_PKCS7_stream(
2747+
bio_out, p7, bio.bio, final_flags
2748+
)
27432749
else:
27442750
assert encoding is serialization.Encoding.DER
27452751
# We need to call finalize here becauase i2d_PKCS7_bio does not

src/cryptography/hazmat/primitives/serialization/base.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ class Encoding(Enum):
4949
OpenSSH = "OpenSSH"
5050
Raw = "Raw"
5151
X962 = "ANSI X9.62"
52+
SMIME = "S/MIME"
5253

5354

5455
class PrivateFormat(Enum):

src/cryptography/hazmat/primitives/serialization/pkcs7.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -71,11 +71,14 @@ def sign(self, encoding, options, backend=None):
7171
options = list(options)
7272
if not all(isinstance(x, PKCS7Options) for x in options):
7373
raise ValueError("options must be from the PKCS7Options enum")
74-
if (
75-
encoding is not serialization.Encoding.PEM
76-
and encoding is not serialization.Encoding.DER
74+
if encoding not in (
75+
serialization.Encoding.PEM,
76+
serialization.Encoding.DER,
77+
serialization.Encoding.SMIME,
7778
):
78-
raise ValueError("Must be PEM or DER from the Encoding enum")
79+
raise ValueError(
80+
"Must be PEM, DER, or SMIME from the Encoding enum"
81+
)
7982

8083
# Text is a meaningless option unless it is accompanied by
8184
# DetachedSignature
@@ -88,12 +91,12 @@ def sign(self, encoding, options, backend=None):
8891
"DetachedSignature"
8992
)
9093

91-
if (
92-
PKCS7Options.Text in options
93-
and encoding is serialization.Encoding.DER
94+
if PKCS7Options.Text in options and encoding in (
95+
serialization.Encoding.DER,
96+
serialization.Encoding.PEM,
9497
):
9598
raise ValueError(
96-
"The Text option does nothing when serializing to DER"
99+
"The Text option is only available for SMIME serialization"
97100
)
98101

99102
# No attributes implies no capabilities so we'll error if you try to

0 commit comments

Comments
 (0)