Exemplo n.º 1
0
def create_degenerate_pkcs7(*certificates: List[x509.Certificate]) -> ContentInfo:
    """Produce a PKCS#7 Degenerate case.

    The degenerate case is a SignedData content type in which there are no signers. Certificates are disseminated
    via the ``certificates`` attribute.

    Args:
         *certificates (List[x509.Certificate]): The certificates to attach to the degenerate pkcs#7 payload.
            The first must always be the issued certificate.
    Returns:
          ContentInfo: The ContentInfo containing a SignedData structure.
    """
    certificates_der = [c.public_bytes(serialization.Encoding.DER) for c in certificates]
    certificates_asn1 = [parse_certificate(der_bytes) for der_bytes in certificates_der]

    # draft-gutmann-scep 3.4. content type must be omitted
    empty = ContentInfo({
        'content_type': ContentType('data')
    })

    sd_certificates = CertificateSet([CertificateChoices('certificate', asn1) for asn1 in certificates_asn1])

    sd = SignedData({
        'version': CMSVersion(1),
        'encap_content_info': empty,
        'digest_algorithms': DigestAlgorithms([]),
        'certificates': sd_certificates,
        'signer_infos': SignerInfos([]),
        'crls': RevocationInfoChoices([]),
    })

    return ContentInfo({
        'content_type': ContentType('signed_data'),
        'content': sd,
    })
Exemplo n.º 2
0
def create_degenerate_certificate(certificate: x509.Certificate) -> ContentInfo:
    """Produce a PKCS#7 Degenerate case with a single certificate.

    Args:
          certificate (x509.Certificate): The certificate to attach to the degenerate pkcs#7 payload.
    Returns:
          ContentInfo: The ContentInfo containing a SignedData structure.
    """
    der_bytes = certificate.public_bytes(
        serialization.Encoding.DER
    )
    asn1cert = parse_certificate(der_bytes)

    empty = ContentInfo({
        'content_type': ContentType('data')
    })
    
    sd = SignedData({
        'version': CMSVersion(1),
        'encap_content_info': empty,
        'digest_algorithms': DigestAlgorithms([]),
        'certificates': CertificateSet([CertificateChoices('certificate', asn1cert)]),
        'signer_infos': SignerInfos([]),
        'crls': RevocationInfoChoices([]),
    })

    return ContentInfo({
        'content_type': ContentType('signed_data'),
        'content': sd,
    })
Exemplo n.º 3
0
    def finalize(self, digest_algorithm):
        """Build all data structures from the given parameters and return the top level contentInfo.

        Returns:
              ContentInfo: The PKIMessage
        """
        pkcs_pki_envelope = self._pki_envelope

        pkienvelope_content_info = ContentInfo({
            'content_type':
            ContentType(u'enveloped_data'),
            'content':
            pkcs_pki_envelope,
        })

        # NOTE: This might not be needed for the degenerate CertRep
        encap_info = ContentInfo({
            'content_type': ContentType(u'data'),
            'content': pkienvelope_content_info.dump()
        })

        # Calculate digest on encrypted content + signed_attrs
        d = digest_for_data(algorithm=digest_algorithm,
                            data=pkienvelope_content_info.dump())

        # Now start building SignedData
        signer_infos = self._build_signerinfos(pkienvelope_content_info.dump(),
                                               d, self._cms_attributes)

        certificates = self._certificates

        da_id = DigestAlgorithmId(six.text_type(digest_algorithm))
        da = DigestAlgorithm({u'algorithm': da_id})
        das = DigestAlgorithms([da])

        sd = SignedData({
            'version': 1,
            'certificates': certificates,
            'signer_infos': signer_infos,
            'digest_algorithms': das,
            'encap_content_info':
            encap_info,  # should point to type data + content contentinfo
        })

        ci = ContentInfo({
            'content_type': ContentType(u'signed_data'),
            'content': sd,
        })

        return ci
Exemplo n.º 4
0
def make_cms(
    cert: Certificate,
    hash_type: int,
    signed_attrs: CMSAttributes,
    sig: bytes,
    unsigned_attrs: Optional[CMSAttributes],
) -> ContentInfo:
    sid = SignerIdentifier(
        "issuer_and_serial_number",
        IssuerAndSerialNumber({
            "issuer":
            cert["tbs_certificate"]["issuer"],
            "serial_number":
            cert["tbs_certificate"]["serial_number"],
        }),
    )

    dg_algo = DigestAlgorithm({"algorithm": _get_digest_algo(hash_type)})

    sig_algo = SignedDigestAlgorithm(
        {"algorithm": SignedDigestAlgorithmId("rsassa_pkcs1v15")})

    sig_info = SignerInfo({
        "version": CMSVersion(1),
        "sid": sid,
        "digest_algorithm": dg_algo,
        "signed_attrs": signed_attrs,
        "signature_algorithm": sig_algo,
        "signature": OctetString(sig),
        "unsigned_attrs": unsigned_attrs,
    })

    certs = make_certificate_chain(cert)

    signed_data = SignedData({
        "version":
        CMSVersion(1),
        "digest_algorithms": [dg_algo],
        "encap_content_info":
        ContentInfo({"content_type": ContentType("data")}),
        "certificates":
        certs,
        "signer_infos": [sig_info],
    })

    return ContentInfo({
        "content_type": ContentType.unmap("signed_data"),
        "content": signed_data
    })
Exemplo n.º 5
0
    def finalize(self) -> Tuple[EnvelopedData, Union[TripleDES, AES], bytes]:
        """Encrypt the data and process the key using all available recipients.
        
        Returns:
              EnvelopedData, TripleDES, iv (bytes): The PKCSPKIEnvelope structure, The symmetric key, and the IV for
              the symmetric key.
        """
        sym_key, iv, ciphertext = self._encrypt_data(self._data)

        eci = EncryptedContentInfo({
            'content_type':
            ContentType('data'),
            'content_encryption_algorithm':
            EncryptionAlgorithm({
                'algorithm': self._encryption_algorithm_id,
                'parameters': OctetString(iv),
            }),
            'encrypted_content':
            ciphertext,
        })

        recipients = [
            self._build_recipient_info(sym_key.key, recipient)
            for recipient in self._recipients
        ]
        recipient_infos = RecipientInfos(recipients)

        ed = EnvelopedData({
            'version': 1,
            'recipient_infos': recipient_infos,
            'encrypted_content_info': eci,
        })

        return ed, sym_key, iv
Exemplo n.º 6
0
    def _build_signerinfos(self, content: bytes, content_digest: bytes, cms_attributes: List[CMSAttribute]) -> SignerInfos:
        """Build all signer infos and return a collection.

        Returns:
            SignerInfos: all signers
        """
        return SignerInfos(signer.sign(content, ContentType('data'), content_digest, cms_attributes) for signer in self._signers)
Exemplo n.º 7
0
def make_signed_attrs(digest: bytes, hash_type: int) -> CMSAttributes:
    content_type = CMSAttribute({
        "type": CMSAttributeType.unmap("content_type"),
        "values": [ContentType.unmap("data")],
    })

    time_now = UTCTime()
    time_now.set(datetime.now(timezone.utc))
    signing_time = CMSAttribute({
        "type": CMSAttributeType.unmap("signing_time"),
        "values": [time_now]
    })

    message_digest = CMSAttribute({
        "type":
        CMSAttributeType.unmap("message_digest"),
        "values": [OctetString(digest)],
    })

    ha_v1 = make_hash_agility_v1(digest)

    ha_v2 = make_hash_agility_v2(digest, hash_type)

    return CMSAttributes(
        [content_type, signing_time, message_digest, ha_v1, ha_v2])
Exemplo n.º 8
0
    def finalize(self) -> ContentInfo:
        """Build all data structures from the given parameters and return the top level contentInfo.

        Returns:
              ContentInfo: The PKIMessage
        """
        pkcs_pki_envelope = self._pki_envelope

        pkienvelope_content_info = ContentInfo({
            'content_type': ContentType('enveloped_data'),
            'content': pkcs_pki_envelope,
        })

        # NOTE: This might not be needed for the degenerate CertRep
        encap_info = ContentInfo({
            'content_type': ContentType('data'),
            'content': pkienvelope_content_info.dump()
        })
        # encap_info_degen = ContentInfo({
        #     'content_type': ContentType('data'),
        #     'content': pkcs_pki_envelope.dump()
        # })

        # Calculate digest on encrypted content + signed_attrs
        #digest = hashes.Hash(hashes.SHA256(), backend=default_backend())
        digest = hashes.Hash(hashes.SHA512(), backend=default_backend())
        #digest = hashes.Hash(hashes.SHA1(), backend=default_backend())
        # digest.update(pkcs_pki_envelope.dump())
        digest.update(pkienvelope_content_info.dump())
        d = digest.finalize()
        
        # Now start building SignedData

        # signer_infos = self._build_signerinfos(pkcs_pki_envelope.dump(), d, self._cms_attributes)
        signer_infos = self._build_signerinfos(pkienvelope_content_info.dump(), d, self._cms_attributes)

        certificates = self._certificates

        #da_id = DigestAlgorithmId('sha256')

        # SHA-1 works for macOS

        # da_id = DigestAlgorithmId('sha1')
        da_id = DigestAlgorithmId('sha512')
        da = DigestAlgorithm({'algorithm': da_id})
        das = DigestAlgorithms([da])

        sd = SignedData({
            'version': 1,
            'certificates': certificates,  
            'signer_infos': signer_infos,
            'digest_algorithms': das,
            'encap_content_info': encap_info,  # should point to type data + content contentinfo
        })

        ci = ContentInfo({
            'content_type': ContentType('signed_data'),
            'content': sd,
        })

        return ci
Exemplo n.º 9
0
    def sign(self):
        h = hashes.Hash(hashes.SHA256(), backend=default_backend())
        h.update(self._content_mime.as_bytes())
        message_digest = h.finalize()

        cs = CertificateSet()
        cs.append(load(self._certificate.public_bytes(Encoding.DER)))

        for ca_cert in self._ca:
            cs.append(load(ca_cert.public_bytes(Encoding.DER)))

        ec = ContentInfo({
            'content_type': ContentType('data'),
        })

        sident = SignerIdentifier({
            'issuer_and_serial_number':
            IssuerAndSerialNumber({
                'issuer':
                load(self._issuer_name.public_bytes(default_backend())),
                'serial_number':
                self._cert_serial,
            })
        })

        certv2 = ESSCertIDv2({
            'hash_algorithm':
            DigestAlgorithm({'algorithm': DigestAlgorithmId('sha256')}),
            'cert_hash':
            OctetString(self._certificate.fingerprint(hashes.SHA256())),
            'issuer_serial':
            IssuerSerial({
                'issuer':
                load(self._issuer_name.public_bytes(default_backend())),
                'serial_number':
                self._cert_serial,
            }),
        })

        now = datetime.now().replace(microsecond=0,
                                     tzinfo=pytz.utc)  # .isoformat()

        sattrs = CMSAttributes({
            CMSAttribute({
                'type': CMSAttributeType('content_type'),
                'values': ["data"]
            }),
            CMSAttribute({
                'type': CMSAttributeType('message_digest'),
                'values': [message_digest]
            }),
            CMSAttribute({
                'type': CMSAttributeType('signing_time'),
                'values': (Time({'utc_time': UTCTime(now)}), )
            }),
            CMSAttribute({
                'type':
                CMSAttributeType('signing_certificate_v2'),
                'values': [SigningCertificateV2({'certs': (certv2, )})]
            })
        })

        signature = self._private_key.sign(sattrs.dump(), padding.PKCS1v15(),
                                           hashes.SHA256())  #

        si = SignerInfo({
            'version':
            'v1',
            'sid':
            sident,
            'digest_algorithm':
            DigestAlgorithm({'algorithm': DigestAlgorithmId('sha256')}),
            'signed_attrs':
            sattrs,
            'signature_algorithm':
            SignedDigestAlgorithm(
                {'algorithm': SignedDigestAlgorithmId('rsassa_pkcs1v15')}),
            'signature':
            signature,
        })

        da = DigestAlgorithms(
            (DigestAlgorithm({'algorithm': DigestAlgorithmId('sha256')}), ))
        signed_data = SignedData({
            'version': 'v1',
            'encap_content_info': ec,
            'certificates': cs,
            'digest_algorithms': da,
            'signer_infos': SignerInfos((si, ))
        })

        ci = ContentInfo({
            'content_type': ContentType('signed_data'),
            'content': signed_data
        })

        self._signature_mime = MIMEApplication(ci.dump(),
                                               _subtype="pkcs7-signature",
                                               name="smime.p7s",
                                               policy=email.policy.SMTPUTF8)
        self._signature_mime.add_header('Content-Disposition',
                                        'attachment; filename=smime.p7s')

        super(CADESMIMESignature, self).attach(self._content_mime)
        super(CADESMIMESignature, self).attach(self._signature_mime)
Exemplo n.º 10
0
    def sign(self):
        h = hashes.Hash(hashes.SHA256(), backend=default_backend())
        h.update(self._content_mime.as_bytes())
        message_digest = h.finalize()

        cs = CertificateSet()
        cs.append(load(self._certificate.public_bytes(Encoding.DER)))

        for ca_cert in self._ca:
            cs.append(load(ca_cert.public_bytes(Encoding.DER)))

        ec = EncapsulatedContentInfo({
            'content_type':
            ContentType('data'),
            'content':
            ParsableOctetString(self._content_mime.as_bytes())
        })

        sident = SignerIdentifier({
            'issuer_and_serial_number':
            IssuerAndSerialNumber({
                'issuer':
                load(self._issuer_name.public_bytes(default_backend())),
                'serial_number':
                self._cert_serial,
            })
        })

        certv2 = ESSCertIDv2({
            'hash_algorithm':
            DigestAlgorithm({'algorithm': DigestAlgorithmId('sha256')}),
            'cert_hash':
            OctetString(self._certificate.fingerprint(hashes.SHA256())),
            'issuer_serial':
            IssuerSerial({
                'issuer':
                load(
                    self._issuer_name.public_bytes(default_backend())
                ),  #[GeneralName({'directory_name': self._issuer_name.public_bytes(default_backend())})],
                'serial_number':
                self._cert_serial,
            }),
        })

        now = datetime.now().replace(microsecond=0, tzinfo=pytz.utc)

        sattrs = CMSAttributes({
            CMSAttribute({
                'type': CMSAttributeType('content_type'),
                'values': ["data"]
            }),
            CMSAttribute({
                'type': CMSAttributeType('message_digest'),
                'values': [message_digest]
            }),
            CMSAttribute({
                'type': CMSAttributeType('signing_time'),
                'values': (Time({'utc_time': UTCTime(now)}), )
            }),
            # isti k v
            CMSAttribute({
                'type':
                CMSAttributeType('signing_certificate_v2'),
                'values': [SigningCertificateV2({'certs': (certv2, )})]
            })
        })

        signature = self._private_key.sign(sattrs.dump(), padding.PKCS1v15(),
                                           hashes.SHA256())

        si = SignerInfo({
            'version':
            'v1',
            'sid':
            sident,
            'digest_algorithm':
            DigestAlgorithm({'algorithm': DigestAlgorithmId('sha256')}),
            'signed_attrs':
            sattrs,
            'signature_algorithm':
            SignedDigestAlgorithm(
                {'algorithm': SignedDigestAlgorithmId('rsassa_pkcs1v15')}),
            'signature':
            signature,
        })

        da = DigestAlgorithms(
            (DigestAlgorithm({'algorithm': DigestAlgorithmId('sha256')}), ))
        signed_data = SignedData({
            'version': 'v3',
            'encap_content_info': ec,
            'certificates': cs,
            'digest_algorithms': da,
            'signer_infos': SignerInfos((si, ))
        })

        ci = ContentInfo({
            'content_type': ContentType('signed_data'),
            'content': signed_data
        })

        self.set_payload(ci.dump())
        encode_base64(self)