Viewing file: pkcs7.py (4.52 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
# 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.
from __future__ import absolute_import, division, print_function
from enum import Enum
from cryptography import x509 from cryptography.hazmat.backends import _get_backend from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import ec, rsa from cryptography.utils import _check_byteslike
def load_pem_pkcs7_certificates(data): backend = _get_backend(None) return backend.load_pem_pkcs7_certificates(data)
def load_der_pkcs7_certificates(data): backend = _get_backend(None) return backend.load_der_pkcs7_certificates(data)
class PKCS7SignatureBuilder(object): def __init__(self, data=None, signers=[], additional_certs=[]): self._data = data self._signers = signers self._additional_certs = additional_certs
def set_data(self, data): _check_byteslike("data", data) if self._data is not None: raise ValueError("data may only be set once")
return PKCS7SignatureBuilder(data, self._signers)
def add_signer(self, certificate, private_key, hash_algorithm): if not isinstance( hash_algorithm, ( hashes.SHA1, hashes.SHA224, hashes.SHA256, hashes.SHA384, hashes.SHA512, ), ): raise TypeError( "hash_algorithm must be one of hashes.SHA1, SHA224, " "SHA256, SHA384, or SHA512" ) if not isinstance(certificate, x509.Certificate): raise TypeError("certificate must be a x509.Certificate")
if not isinstance( private_key, (rsa.RSAPrivateKey, ec.EllipticCurvePrivateKey) ): raise TypeError("Only RSA & EC keys are supported at this time.")
return PKCS7SignatureBuilder( self._data, self._signers + [(certificate, private_key, hash_algorithm)], )
def add_certificate(self, certificate): if not isinstance(certificate, x509.Certificate): raise TypeError("certificate must be a x509.Certificate")
return PKCS7SignatureBuilder( self._data, self._signers, self._additional_certs + [certificate] )
def sign(self, encoding, options, backend=None): if len(self._signers) == 0: raise ValueError("Must have at least one signer") if self._data is None: raise ValueError("You must add data to sign") options = list(options) if not all(isinstance(x, PKCS7Options) for x in options): raise ValueError("options must be from the PKCS7Options enum") if encoding not in ( serialization.Encoding.PEM, serialization.Encoding.DER, serialization.Encoding.SMIME, ): raise ValueError( "Must be PEM, DER, or SMIME from the Encoding enum" )
# Text is a meaningless option unless it is accompanied by # DetachedSignature if ( PKCS7Options.Text in options and PKCS7Options.DetachedSignature not in options ): raise ValueError( "When passing the Text option you must also pass " "DetachedSignature" )
if PKCS7Options.Text in options and encoding in ( serialization.Encoding.DER, serialization.Encoding.PEM, ): raise ValueError( "The Text option is only available for SMIME serialization" )
# No attributes implies no capabilities so we'll error if you try to # pass both. if ( PKCS7Options.NoAttributes in options and PKCS7Options.NoCapabilities in options ): raise ValueError( "NoAttributes is a superset of NoCapabilities. Do not pass " "both values." )
backend = _get_backend(backend) return backend.pkcs7_sign(self, encoding, options)
class PKCS7Options(Enum): Text = "Add text/plain MIME type" Binary = "Don't translate input data into canonical MIME format" DetachedSignature = "Don't embed data in the PKCS7 structure" NoCapabilities = "Don't embed SMIME capabilities" NoAttributes = "Don't embed authenticatedAttributes" NoCerts = "Don't embed signer certificate"
|