예제 #1
0
def _sort_attributes(attrs_in: CMSAttributes) -> CMSAttributes:
    """
    Sort the authenticated attributes for signing by re-encoding them, asn1crypto
    takes care of the actual sorting of the set.
    """
    attrs_out = CMSAttributes()
    for attrval in attrs_in:
        attrs_out.append(attrval)
    return attrs_out
예제 #2
0
    def _build_cmsattributes(self) -> CMSAttributes:
        """Finalize the set of CMS Attributes and return the collection.

        Returns:
              CMSAttributes: All of the added CMS attributes
        """
        return CMSAttributes(value=self._cms_attributes)
예제 #3
0
파일: sign.py 프로젝트: achow101/signapple
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])
예제 #4
0
파일: sign.py 프로젝트: achow101/signapple
    def make_signature(self):
        assert self.sig.code_dir_blob

        # Redo the code hashes
        self._set_code_hashes()

        # Make the signature
        signed_attrs: CMSAttributes = make_signed_attrs(
            self.sig.code_dir_blob.get_hash(self.hash_type), self.hash_type)
        actual_privkey = load_private_key(self.privkey)
        signature = rsa_pkcs1v15_sign(actual_privkey, signed_attrs.dump(),
                                      self.hash_type_str)

        # Get the timestamp from Apple
        digest = get_hash(signature, self.hash_type)
        tst = CMSAttribute({
            "type":
            CMSAttributeType("signature_time_stamp_token"),
            "values": [get_timestamp_token(digest, self.hash_type)],
        })

        # Make the CMS
        self.sig.sig_blob = SignatureBlob()
        self.sig.sig_blob.cms = make_cms(self.cert, self.hash_type,
                                         signed_attrs, signature,
                                         CMSAttributes([tst]))

        # Get the CodeSignature section. It should be the last in the binary
        cs_sec = self.macho.sect[-1]
        assert cs_sec == self.get_linkedit_segment().sect[-1]
        assert isinstance(cs_sec, CodeSignature)
        sig_cmd = self.get_sig_command()

        # Serialize the signature
        f = BytesIO()
        self.sig.serialize(f)
        f.write((sig_cmd.datasize - f.tell()) * b"\x00")

        if self.detach_target:
            target_dir = os.path.join(self.detach_target, "Contents", "MacOS")
            os.makedirs(target_dir, exist_ok=True)
            target_file = os.path.join(
                target_dir,
                os.path.basename(self.filename) +
                f".{CPU_NAMES[self.macho.Mhdr.cputype]}sign",
            )
            with open(target_file, "wb") as tf:
                tf.write(f.getvalue())
                self.files_modified.append(target_file)
        else:
            # Set the section's content to be the signature
            cs_sec.content = StrPatchwork(f.getvalue())
예제 #5
0
    def sign(self,
             data: bytes,
             content_type: ContentType,
             content_digest: bytes,
             cms_attributes: List[CMSAttribute]) -> SignerInfo:
        """Generate a signature encrypted with the signer's private key and return the SignerInfo."""
        
        # The CMS standard requires that the content-type authenticatedAttribute and the message-digest
        # attribute must be present if any authenticatedAttribute exists at all.
        self.signed_attributes = cms_attributes

        self.signed_attributes.insert(0, CMSAttribute({
            'type': 'signing_time',
            'values': [GeneralizedTime(datetime.datetime.utcnow())]
        }))

        self.signed_attributes.insert(0, CMSAttribute({
            'type': 'message_digest',
            'values': [OctetString(content_digest)],
        }))

        # This refers to whatever the content of EncapsulatedContentInfo is
        self.signed_attributes.insert(0, CMSAttribute({
            'type': 'content_type',
            'values': [content_type],
        }))

        cms_attributes = CMSAttributes(self.signed_attributes)

        # NOTE: no need to calculate this digest as .signer() does the hashing

        # RFC5652
        # The message digest is
        # computed on either the content being signed or the content
        # together with the signed attributes using the process described in
        # Section 5.4.
        # digest = hashes.Hash(hashes.SHA256(), backend=default_backend())

        # the initial input is the encapContentInfo eContent OCTET STRING
        # RFC5652 Section 5.4 - When the field (signed_attrs) is present, however, the result is the message
        # digest of the complete DER encoding of the SignedAttrs value
        # contained in the signedAttrs field.
        # NOTE: it is not clear whether data is included
        #digest.update(data)
        # digest.update(cms_attributes.dump())
        # d = digest.finalize()

        # Make DigestInfo from result
        # NOTE: It is not clear whether this applies: RFC5652 - Section 5.5.
        # digest_info = DigestInfo({
        #     'digest_algorithm': self.digest_algorithm,
        #     'digest': d,
        # })

        # Get the RSA key to sign the digestinfo
        digest_function = {
            'sha1': hashes.SHA1,  # macOS
            'sha256': hashes.SHA256,
            'sha512': hashes.SHA512
        }[self.digest_algorithm_id.native]

        signer = self.private_key.signer(
            asympad.PKCS1v15(),
            digest_function(),
        )

        # NOTE: this is not the digest `d` above because crypto.io already hashes stuff for us!!
        signer.update(cms_attributes.dump())
        signature = signer.finalize()

        signer_info = SignerInfo({
            # Version must be 1 if signer uses IssuerAndSerialNumber as sid
            'version': CMSVersion(1),
            'sid': self.sid,
            
            'digest_algorithm': self.digest_algorithm,
            'signed_attrs': cms_attributes,

            # Referred to as ``digestEncryptionAlgorithm`` in the RFC
            'signature_algorithm': self.signed_digest_algorithm,

            # Referred to as ``encryptedDigest`` in the RFC
            'signature': OctetString(signature),
        })

        return signer_info
예제 #6
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)
예제 #7
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)
예제 #8
0
    def sign(self, data, content_type, content_digest, cms_attributes):
        """Generate a signature encrypted with the signer's private key and return the SignerInfo."""

        # The CMS standard requires that the content-type authenticatedAttribute and the message-digest
        # attribute must be present if any authenticatedAttribute exists at all.
        self.signed_attributes = cms_attributes

        # NDES does not even include this
        # self.signed_attributes.insert(0, CMSAttribute({
        #     'type': 'signing_time',
        #     'values': [GeneralizedTime(datetime.datetime.utcnow())]
        # }))

        self.signed_attributes.insert(
            0,
            CMSAttribute({
                'type': u'message_digest',
                'values': [OctetString(content_digest)],
            }))

        # This refers to whatever the content of EncapsulatedContentInfo is
        self.signed_attributes.insert(
            0,
            CMSAttribute({
                'type': u'content_type',
                'values': [content_type],
            }))

        cms_attributes = CMSAttributes(self.signed_attributes)

        # NOTE: no need to calculate this digest as .signer() does the hashing

        # RFC5652
        # The message digest is
        # computed on either the content being signed or the content
        # together with the signed attributes using the process described in
        # Section 5.4.
        # digest = hashes.Hash(hashes.SHA256(), backend=default_backend())

        # the initial input is the encapContentInfo eContent OCTET STRING
        # RFC5652 Section 5.4 - When the field (signed_attrs) is present, however, the result is the message
        # digest of the complete DER encoding of the SignedAttrs value
        # contained in the signedAttrs field.
        # NOTE: it is not clear whether data is included
        #digest.update(data)
        # digest.update(cms_attributes.dump())
        # d = digest.finalize()

        # Make DigestInfo from result
        # NOTE: It is not clear whether this applies: RFC5652 - Section 5.5.
        # digest_info = DigestInfo({
        #     'digest_algorithm': self.digest_algorithm,
        #     'digest': d,
        # })

        signature = self.private_key.sign(
            data=cms_attributes.dump(),
            padding_type='pkcs',
            algorithm=self.digest_algorithm_id.native)

        signer_info = SignerInfo({
            # Version must be 1 if signer uses IssuerAndSerialNumber as sid
            'version': CMSVersion(1),
            'sid': self.sid,
            'digest_algorithm': self.digest_algorithm,
            'signed_attrs': cms_attributes,

            # Referred to as ``digestEncryptionAlgorithm`` in the RFC
            'signature_algorithm': self.signed_digest_algorithm,

            # Referred to as ``encryptedDigest`` in the RFC
            'signature': OctetString(signature),
        })

        return signer_info