async def test_no_certificates(delete): input_buf = BytesIO(MINIMAL) w = IncrementalPdfFileWriter(input_buf) md_algorithm = 'sha256' cms_writer = cms_embedder.PdfCMSEmbedder().write_cms( field_name='Signature', writer=w ) next(cms_writer) sig_obj = signers.SignatureObject(bytes_reserved=8192) cms_writer.send(cms_embedder.SigObjSetup(sig_placeholder=sig_obj)) prep_digest, output = cms_writer.send( cms_embedder.SigIOSetup(md_algorithm=md_algorithm, in_place=True) ) signer: signers.SimpleSigner = signers.SimpleSigner( signing_cert=FROM_CA.signing_cert, signing_key=FROM_CA.signing_key, cert_registry=FROM_CA.cert_registry, signature_mechanism=SignedDigestAlgorithm({ 'algorithm': 'rsassa_pkcs1v15' }) ) cms_obj = await signer.async_sign( data_digest=prep_digest.document_digest, digest_algorithm=md_algorithm, ) sd = cms_obj['content'] if delete: del sd['certificates'] else: sd['certificates'] = cms.CertificateSet([]) cms_writer.send(cms_obj) r = PdfFileReader(output) with pytest.raises(CMSExtractionError, match='signer cert.*includ'): emb = r.embedded_signatures[0] await collect_validation_info( embedded_sig=emb, validation_context=ValidationContext() ) with pytest.raises(SignatureValidationError, match='signer cert.*includ'): r.embedded_signatures[0].signer_cert.dump()
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()
def sign_message( data_to_sign, digest_alg, sign_key, sign_alg="rsassa_pkcs1v15", 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 sign_alg: The algorithm to be used for signing the message. :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("2.16.840.1.101.3.4.1.42")) ]), ), ( "1", OrderedDict([ ("0", core.ObjectIdentifier("2.16.840.1.101.3.4.1.2")) ]), ), ( "2", OrderedDict([("0", core.ObjectIdentifier("1.2.840.113549.3.7")) ]), ), ( "3", OrderedDict([ ("0", core.ObjectIdentifier("1.2.840.113549.3.2")), ("1", core.Integer(128)), ]), ), ( "4", 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.utcnow().replace(tzinfo=timezone.utc)) }) ]), }), 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))]), }), ]) else: signed_attributes = None # Generate the signature data_to_sign = signed_attributes.dump( ) if signed_attributes else data_to_sign if sign_alg == "rsassa_pkcs1v15": signature = asymmetric.rsa_pkcs1v15_sign(sign_key[0], data_to_sign, digest_alg) elif sign_alg == "rsassa_pss": signature = asymmetric.rsa_pss_sign(sign_key[0], data_to_sign, digest_alg) else: raise AS2Exception("Unsupported Signature Algorithm") 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(sign_alg)}), "signature": core.OctetString(signature), }) ]), }), }).dump()