Exemplo n.º 1
0
def compress_message(data_to_compress):
    """Function compresses data and returns the generated ASN.1

    :param data_to_compress: A byte string of the data to be compressed

    :return: A CMS ASN.1 byte string of the compressed data.
    """
    compressed_content = cms.ParsableOctetString(
        zlib.compress(data_to_compress))
    return cms.ContentInfo({
        "content_type":
        cms.ContentType("compressed_data"),
        "content":
        cms.CompressedData({
            "version":
            cms.CMSVersion("v0"),
            "compression_algorithm":
            cms.CompressionAlgorithm(
                {"algorithm": cms.CompressionAlgorithmId("zlib")}),
            "encap_content_info":
            cms.EncapsulatedContentInfo({
                "content_type": cms.ContentType("data"),
                "content": compressed_content,
            }),
        }),
    }).dump()
Exemplo n.º 2
0
async def test_cms_v3_sign(detached):
    inner_obj = await FROM_CA.async_sign_general_data(
        b'Hello world!', 'sha256', detached=False
    )

    signature = await FROM_CA.async_sign_general_data(
        cms.EncapsulatedContentInfo({
            'content_type': 'signed_data',
            'content': inner_obj['content'].untag()
        }),
        'sha256',
        detached=detached
    )

    # re-parse just to make sure we're starting fresh
    signature = cms.ContentInfo.load(signature.dump())

    content = signature['content']
    assert content['version'].native == 'v3'
    assert isinstance(content, cms.SignedData)
    eci = content['encap_content_info']
    assert eci['content_type'].native == 'signed_data'
    if detached:
        raw_digest = hashlib.sha256(
            inner_obj['content'].untag().dump()
        ).digest()
    else:
        raw_digest = None
        inner_eci = eci['content'].parsed['encap_content_info']
        assert inner_eci['content'].native == b'Hello world!'
    status = await async_validate_cms_signature(
        content, raw_digest=raw_digest
    )
    assert status.valid
    assert status.intact
Exemplo n.º 3
0
def compress_message(data_to_compress):
    """Function compresses data and returns the generated ASN.1
    
    :param data_to_compress: A byte string of the data to be compressed
    
    :return: A CMS ASN.1 byte string of the compressed data.    
    """
    compressed_content = cms.ParsableOctetString(
        zlib.compress(data_to_compress))
    return cms.ContentInfo({
        'content_type':
        cms.ContentType('compressed_data'),
        'content':
        cms.CompressedData({
            'version':
            cms.CMSVersion('v0'),
            'compression_algorithm':
            cms.CompressionAlgorithm(
                {'algorithm': cms.CompressionAlgorithmId('zlib')}),
            'encap_content_info':
            cms.EncapsulatedContentInfo({
                'content_type': cms.ContentType('data'),
                'content': compressed_content
            })
        })
    }).dump()
Exemplo n.º 4
0
def sign_authpack_native(data, privkey, certificate, wrap_signed=False):
    """
    Creating PKCS7 blob which contains the following things:
    1. 'data' blob which is an ASN1 encoded "AuthPack" structure
    2. the certificate used to sign the data blob
    3. the singed 'signed_attrs' structure (ASN1) which points to the "data" structure (in point 1)
    """

    da = {'algorithm': algos.DigestAlgorithmId('1.3.14.3.2.26')}

    si = {}
    si['version'] = 'v1'
    si['sid'] = cms.IssuerAndSerialNumber({
        'issuer':
        certificate.issuer,
        'serial_number':
        certificate.serial_number,
    })

    si['digest_algorithm'] = algos.DigestAlgorithm(da)
    si['signed_attrs'] = [
        cms.CMSAttribute({
            'type': 'content_type',
            'values': ['1.3.6.1.5.2.3.1']
        }),
        # indicates that the encap_content_info's authdata struct (marked with OID '1.3.6.1.5.2.3.1' is signed )
        cms.CMSAttribute({
            'type': 'message_digest',
            'values': [hashlib.sha1(data).digest()]
        }),
        ### hash of the data, the data itself will not be signed, but this block of data will be.
    ]
    si['signature_algorithm'] = algos.SignedDigestAlgorithm(
        {'algorithm': '1.2.840.113549.1.1.1'})
    si['signature'] = rsa_pkcs1v15_sign(
        privkey,
        cms.CMSAttributes(si['signed_attrs']).dump(), "sha1")

    ec = {}
    ec['content_type'] = '1.3.6.1.5.2.3.1'
    ec['content'] = data

    sd = {}
    sd['version'] = 'v3'
    sd['digest_algorithms'] = [algos.DigestAlgorithm(da)]  # must have only one
    sd['encap_content_info'] = cms.EncapsulatedContentInfo(ec)
    sd['certificates'] = [certificate]
    sd['signer_infos'] = cms.SignerInfos([cms.SignerInfo(si)])

    if wrap_signed is True:
        ci = {}
        ci['content_type'] = '1.2.840.113549.1.7.2'  # signed data OID
        ci['content'] = cms.SignedData(sd)
        return cms.ContentInfo(ci).dump()

    return cms.SignedData(sd).dump()
Exemplo n.º 5
0
def compress_message(data_to_compress):
    compressed_content = cms.ParsableOctetString(
        zlib.compress(data_to_compress))
    return cms.ContentInfo({
        'content_type':
        cms.ContentType('compressed_data'),
        'content':
        cms.CompressedData({
            'version':
            cms.CMSVersion(0),
            'compression_algorithm':
            cms.CompressionAlgorithm(
                {'algorithm': cms.CompressionAlgorithmId('zlib')}),
            'encap_content_info':
            cms.EncapsulatedContentInfo({
                'content_type': cms.ContentType('data'),
                'content': compressed_content
            })
        })
    })
Exemplo n.º 6
0
    assert status.valid
    assert status.intact
    assert 'CONTENT_TIMESTAMP_TOKEN<INVALID>' in status.summary()
    assert 'TIMESTAMP_TOKEN<INTACT:UNTRUSTED>' in status.summary()


@freeze_time('2020-11-01')
@pytest.mark.parametrize('content,detach', [
    (b'This is not a TST!', True),
    (b'This is not a TST!', False),
    (cms.ContentInfo({
        'content_type': 'data', 'content': b'This is not a TST!'
    }), False),
    (cms.EncapsulatedContentInfo({
        'content_type': '2.999',
        'content': core.ParsableOctetString(
            core.OctetString(b'This is not a TST!').dump()
        )
    }), False),
    (cms.ContentInfo({'content_type': '2.999',}), True),
])
async def test_detached_with_malformed_content_tst(content, detach):
    class CustomProvider(CMSAttributeProvider):
        attribute_type = 'content_time_stamp'

        async def build_attr_value(self, dry_run=False):
            attr_value = await FROM_CA.async_sign_general_data(
                content, 'sha256',
                detached=detach,
            )
            return attr_value
Exemplo n.º 7
0
    def request_tsa_response(self, req: tsp.TimeStampReq) -> tsp.TimeStampResp:
        # We pretend that certReq is always true in the request

        # TODO generalise my detached signature logic to include cases like this
        #  (see § 5.4 in RFC 5652)
        # TODO does the RFC
        status = tsp.PKIStatusInfo({'status': tsp.PKIStatus('granted')})
        message_imprint: tsp.MessageImprint = req['message_imprint']
        md_algorithm = message_imprint['hash_algorithm']['algorithm'].native
        digest_algorithm_obj = algos.DigestAlgorithm({
            'algorithm': md_algorithm
        })
        dt = self.fixed_dt or datetime.now(tz=tzlocal.get_localzone())
        tst_info = {
            'version': 'v1',
            # See http://oidref.com/1.3.6.1.4.1.4146.2.2
            # I don't really care too much, this is a testing device anyway
            'policy': tsp.ObjectIdentifier('1.3.6.1.4.1.4146.2.2'),
            'message_imprint': message_imprint,
            # should be sufficiently random (again, this is a testing class)
            'serial_number': get_nonce(),
            'gen_time': dt,
            'tsa': x509.GeneralName(
                name='directory_name', value=self.tsa_cert.subject
            )
        }
        try:
            tst_info['nonce'] = req['nonce']
        except KeyError:
            pass

        tst_info = tsp.TSTInfo(tst_info)
        tst_info_data = tst_info.dump()
        message_digest = getattr(hashlib, md_algorithm)(tst_info_data).digest()
        signed_attrs = cms.CMSAttributes([
            simple_cms_attribute('content_type', 'tst_info'),
            simple_cms_attribute(
                'signing_time', cms.Time({'utc_time': core.UTCTime(dt)})
            ),
            simple_cms_attribute(
                'signing_certificate',
                general.as_signing_certificate(self.tsa_cert)
            ),
            simple_cms_attribute('message_digest', message_digest),
        ])
        signature = asymmetric.rsa_pkcs1v15_sign(
            asymmetric.load_private_key(self.tsa_key),
            signed_attrs.dump(), md_algorithm
        )
        sig_info = cms.SignerInfo({
            'version': 'v1',
            'sid': cms.SignerIdentifier({
                'issuer_and_serial_number': cms.IssuerAndSerialNumber({
                    'issuer': self.tsa_cert.issuer,
                    'serial_number': self.tsa_cert.serial_number,
                })
            }),
            'digest_algorithm': digest_algorithm_obj,
            'signature_algorithm': algos.SignedDigestAlgorithm(
                {'algorithm': 'rsassa_pkcs1v15'}
            ),
            'signed_attrs': signed_attrs,
            'signature': signature
        })
        certs = set(self.certs_to_embed)
        certs.add(self.tsa_cert)
        signed_data = {
            # must use v3 to get access to the EncapsulatedContentInfo construct
            'version': 'v3',
            'digest_algorithms': cms.DigestAlgorithms((digest_algorithm_obj,)),
            'encap_content_info': cms.EncapsulatedContentInfo({
                'content_type': cms.ContentType('tst_info'),
                'content': cms.ParsableOctetString(tst_info_data)
            }),
            'certificates': certs,
            'signer_infos': [sig_info]
        }
        tst = cms.ContentInfo({
            'content_type': cms.ContentType('signed_data'),
            'content': cms.SignedData(signed_data)
        })
        return tsp.TimeStampResp({'status': status, 'time_stamp_token': tst})
Exemplo n.º 8
0
    def request_tsa_response(self, req: tsp.TimeStampReq) -> tsp.TimeStampResp:
        # We pretend that certReq is always true in the request

        status = tsp.PKIStatusInfo({'status': tsp.PKIStatus('granted')})
        message_imprint: tsp.MessageImprint = req['message_imprint']
        md_algorithm = self.md_algorithm
        digest_algorithm_obj = algos.DigestAlgorithm({
            'algorithm': md_algorithm
        })
        dt = self.fixed_dt or datetime.now(tz=tzlocal.get_localzone())
        tst_info = {
            'version': 'v1',
            'policy': self.policy,
            'message_imprint': message_imprint,
            'serial_number': get_nonce(),
            'gen_time': dt,
            'tsa': x509.GeneralName(
                name='directory_name', value=self.tsa_cert.subject
            )
        }
        try:
            tst_info['nonce'] = req['nonce']
        except KeyError:
            pass

        tst_info = tsp.TSTInfo(tst_info)
        tst_info_data = tst_info.dump()
        message_digest = getattr(hashlib, md_algorithm)(tst_info_data).digest()
        signing_cert_id = tsp.ESSCertID({
            'cert_hash': hashlib.sha1(self.tsa_cert.dump()).digest()
        })
        signed_attrs = cms.CMSAttributes([
            simple_cms_attribute('content_type', 'tst_info'),
            simple_cms_attribute(
                'signing_time', cms.Time({'utc_time': core.UTCTime(dt)})
            ),
            simple_cms_attribute(
                'signing_certificate',
                tsp.SigningCertificate({'certs': [signing_cert_id]})
            ),
            simple_cms_attribute('message_digest', message_digest),
        ])
        signature = generic_sign(
            self.tsa_key, signed_attrs.dump(), self.signature_algo
        )
        sig_info = cms.SignerInfo({
            'version': 'v1',
            'sid': cms.SignerIdentifier({
                'issuer_and_serial_number': cms.IssuerAndSerialNumber({
                    'issuer': self.tsa_cert.issuer,
                    'serial_number': self.tsa_cert.serial_number,
                })
            }),
            'digest_algorithm': digest_algorithm_obj,
            'signature_algorithm': self.signature_algo,
            'signed_attrs': signed_attrs,
            'signature': signature
        })
        certs = set(self.certs_to_embed)
        certs.add(self.tsa_cert)
        signed_data = {
            # must use v3 to get access to the EncapsulatedContentInfo construct
            'version': 'v3',
            'digest_algorithms': cms.DigestAlgorithms((digest_algorithm_obj,)),
            'encap_content_info': cms.EncapsulatedContentInfo({
                'content_type': cms.ContentType('tst_info'),
                'content': cms.ParsableOctetString(tst_info_data)
            }),
            'certificates': certs,
            'signer_infos': [sig_info]
        }
        tst = cms.ContentInfo({
            'content_type': cms.ContentType('signed_data'),
            'content': cms.SignedData(signed_data)
        })
        return tsp.TimeStampResp({'status': status, 'time_stamp_token': tst})
Exemplo n.º 9
0
    def request_tsa_response(self, req: tsp.TimeStampReq) \
            -> tsp.TimeStampResp:
        # We pretend that certReq is always true in the request

        # TODO generalise my detached signature logic to include cases like this
        #  (see § 5.4 in RFC 5652)
        # TODO does the RFC
        status = tsp.PKIStatusInfo({'status': tsp.PKIStatus('granted')})
        message_imprint: tsp.MessageImprint = req['message_imprint']
        md_algorithm = self.override_md
        if md_algorithm is None:
            md_algorithm = message_imprint['hash_algorithm'][
                'algorithm'].native
        digest_algorithm_obj = algos.DigestAlgorithm(
            {'algorithm': md_algorithm})
        dt = self.fixed_dt or datetime.now(tz=tzlocal.get_localzone())
        tst_info = {
            'version':
            'v1',
            # See http://oidref.com/1.3.6.1.4.1.4146.2.2
            # I don't really care too much, this is a testing device anyway
            'policy':
            tsp.ObjectIdentifier('1.3.6.1.4.1.4146.2.2'),
            'message_imprint':
            message_imprint,
            # should be sufficiently random (again, this is a testing class)
            'serial_number':
            get_nonce(),
            'gen_time':
            dt,
            'tsa':
            x509.GeneralName(name='directory_name',
                             value=self.tsa_cert.subject)
        }
        if req['nonce'].native is not None:
            tst_info['nonce'] = req['nonce']

        tst_info = tsp.TSTInfo(tst_info)
        tst_info_data = tst_info.dump()
        md_spec = get_pyca_cryptography_hash(md_algorithm)
        md = hashes.Hash(md_spec)
        md.update(tst_info_data)
        message_digest_value = md.finalize()
        signed_attrs = cms.CMSAttributes([
            simple_cms_attribute('content_type', 'tst_info'),
            simple_cms_attribute('signing_time',
                                 cms.Time({'utc_time': core.UTCTime(dt)})),
            simple_cms_attribute('signing_certificate',
                                 general.as_signing_certificate(
                                     self.tsa_cert)),
            simple_cms_attribute('message_digest', message_digest_value),
        ])
        priv_key = serialization.load_der_private_key(self.tsa_key.dump(),
                                                      password=None)
        if not isinstance(priv_key, RSAPrivateKey):
            raise NotImplementedError("Dummy timestamper is RSA-only.")
        signature = priv_key.sign(
            signed_attrs.dump(), PKCS1v15(),
            get_pyca_cryptography_hash(md_algorithm.upper()))
        sig_info = cms.SignerInfo({
            'version':
            'v1',
            'sid':
            cms.SignerIdentifier({
                'issuer_and_serial_number':
                cms.IssuerAndSerialNumber({
                    'issuer':
                    self.tsa_cert.issuer,
                    'serial_number':
                    self.tsa_cert.serial_number,
                })
            }),
            'digest_algorithm':
            digest_algorithm_obj,
            'signature_algorithm':
            algos.SignedDigestAlgorithm({'algorithm': 'rsassa_pkcs1v15'}),
            'signed_attrs':
            signed_attrs,
            'signature':
            signature
        })
        certs = set(self.certs_to_embed)
        certs.add(self.tsa_cert)
        signed_data = {
            # must use v3 to get access to the EncapsulatedContentInfo construct
            'version':
            'v3',
            'digest_algorithms':
            cms.DigestAlgorithms((digest_algorithm_obj, )),
            'encap_content_info':
            cms.EncapsulatedContentInfo({
                'content_type':
                cms.ContentType('tst_info'),
                'content':
                cms.ParsableOctetString(tst_info_data)
            }),
            'certificates':
            certs,
            'signer_infos': [sig_info]
        }
        tst = cms.ContentInfo({
            'content_type': cms.ContentType('signed_data'),
            'content': cms.SignedData(signed_data)
        })
        return tsp.TimeStampResp({'status': status, 'time_stamp_token': tst})