Function signs the data and returns the generated ASN.1

    :param data_to_sign: A byte string of the data to be signed.

    :param digest_alg: 
        The digest algorithm to be used for generating the signature.

    :param sign_key: The key to be used for generating the signature.
    
    :param use_signed_attributes: Optional attribute to indicate weather the 
    CMS signature attributes should be included in the signature or not.

    :return: A CMS ASN.1 byte string of the signed data.

def sign_message(data_to_sign, digest_alg, sign_key,
                 use_signed_attributes=True):
    """Function signs the data and returns the generated ASN.1

    :param data_to_sign: A byte string of the data to be signed.

    :param digest_alg: 
        The digest algorithm to be used for generating the signature.

    :param sign_key: The key to be used for generating the signature.
    
    :param use_signed_attributes: Optional attribute to indicate weather the 
    CMS signature attributes should be included in the signature or not.

    :return: A CMS ASN.1 byte string of the signed data.    
    """

    if use_signed_attributes:
        digest_func = hashlib.new(digest_alg)
        digest_func.update(data_to_sign)
        message_digest = digest_func.digest()

        class SmimeCapability(core.Sequence):
            _fields = [
                ('0', core.Any, {'optional': True}),
                ('1', core.Any, {'optional': True}),
                ('2', core.Any, {'optional': True}),
                ('3', core.Any, {'optional': True}),
                ('4', core.Any, {'optional': True})
            ]

        class SmimeCapabilities(core.Sequence):
            _fields = [
                ('0', SmimeCapability),
                ('1', SmimeCapability, {'optional': True}),
                ('2', SmimeCapability, {'optional': True}),
                ('3', SmimeCapability, {'optional': True}),
                ('4', SmimeCapability, {'optional': True}),
                ('5', SmimeCapability, {'optional': True}),
            ]

        smime_cap = OrderedDict([
            ('0', OrderedDict([
                ('0', core.ObjectIdentifier('1.2.840.113549.3.7'))])),
            ('1', OrderedDict([
                ('0', core.ObjectIdentifier('1.2.840.113549.3.2')),
                ('1', core.Integer(128))])),
            ('2', OrderedDict([
                ('0', core.ObjectIdentifier('1.2.840.113549.3.4')),
                ('1', core.Integer(128))])),
        ])

        signed_attributes = cms.CMSAttributes([
            cms.CMSAttribute({
                'type': cms.CMSAttributeType('content_type'),
                'values': cms.SetOfContentType([
                    cms.ContentType('data')
                ])
            }),
            cms.CMSAttribute({
                'type': cms.CMSAttributeType('signing_time'),
                'values': cms.SetOfTime([
                    cms.Time({
                        'utc_time': core.UTCTime(datetime.now())
                    })
                ])
            }),
            cms.CMSAttribute({
                'type': cms.CMSAttributeType('message_digest'),
                'values': cms.SetOfOctetString([
                    core.OctetString(message_digest)
                ])
            }),
            cms.CMSAttribute({
                'type': cms.CMSAttributeType('1.2.840.113549.1.9.15'),
                'values': cms.SetOfAny([
                    core.Any(SmimeCapabilities(smime_cap))
                ])
            }),
        ])
        signature = asymmetric.rsa_pkcs1v15_sign(
            sign_key[0], signed_attributes.dump(), digest_alg)
    else:
        signed_attributes = None
        signature = asymmetric.rsa_pkcs1v15_sign(
            sign_key[0], data_to_sign, digest_alg)

    return cms.ContentInfo({
        'content_type': cms.ContentType('signed_data'),
        'content': cms.SignedData({
            'version': cms.CMSVersion('v1'),
            'digest_algorithms': cms.DigestAlgorithms([
                algos.DigestAlgorithm({
                    'algorithm': algos.DigestAlgorithmId(digest_alg)
                })
            ]),
            'encap_content_info': cms.ContentInfo({
                'content_type': cms.ContentType('data')
            }),
            'certificates': cms.CertificateSet([
                cms.CertificateChoices({
                    'certificate': sign_key[1].asn1
                })
            ]),
            'signer_infos': cms.SignerInfos([
                cms.SignerInfo({
                    'version': cms.CMSVersion('v1'),
                    'sid': cms.SignerIdentifier({
                        'issuer_and_serial_number': cms.IssuerAndSerialNumber({
                            'issuer': sign_key[1].asn1[
                                'tbs_certificate']['issuer'],
                            'serial_number': sign_key[1].asn1[
                                'tbs_certificate']['serial_number']
                        })
                    }),
                    'digest_algorithm': algos.DigestAlgorithm({
                        'algorithm': algos.DigestAlgorithmId(digest_alg)
                    }),
                    'signed_attrs': signed_attributes,
                    'signature_algorithm': algos.SignedDigestAlgorithm({
                        'algorithm':
                            algos.SignedDigestAlgorithmId('rsassa_pkcs1v15')
                    }),
                    'signature': core.OctetString(signature)
                })
            ])
        })
    }).dump()