Ejemplo n.º 1
0
def test_sv_sign_addrevinfo_subfilter_conflict():
    sv = fields.SigSeedValueSpec(flags=fields.SigSeedValFlags.ADD_REV_INFO,
                                 subfilters=[PADES],
                                 add_rev_info=True)
    with pytest.raises(SigningError):
        meta = signers.PdfSignatureMetadata(field_name='Sig',
                                            validation_context=dummy_ocsp_vc(),
                                            embed_validation_info=True)
        sign_with_sv(sv, meta)

    revinfo_and_subfilter = (fields.SigSeedValFlags.ADD_REV_INFO
                             | fields.SigSeedValFlags.SUBFILTER)
    sv = fields.SigSeedValueSpec(flags=revinfo_and_subfilter,
                                 subfilters=[PADES],
                                 add_rev_info=True)
    meta = signers.PdfSignatureMetadata(field_name='Sig',
                                        validation_context=dummy_ocsp_vc(),
                                        embed_validation_info=True)
    with pytest.raises(SigningError):
        sign_with_sv(sv, meta)
    sign_with_sv(sv, meta, test_violation=True)

    sv = fields.SigSeedValueSpec(flags=revinfo_and_subfilter,
                                 subfilters=[PADES],
                                 add_rev_info=False)
    meta = signers.PdfSignatureMetadata(
        field_name='Sig',
        validation_context=dummy_ocsp_vc(),
    )
    sign_with_sv(sv, meta)
Ejemplo n.º 2
0
def test_sv_version():
    fields.SigSeedValueSpec.from_pdf_object(
        generic.DictionaryObject({'/Ff': fields.SigSeedValFlags.V}))
    fields.SigSeedValueSpec.from_pdf_object(
        fields.SigSeedValueSpec(flags=fields.SigSeedValFlags.V,
                                sv_dict_version=fields.SeedValueDictVersion.
                                PDF_2_0).as_pdf_object())
    with pytest.raises(SigningError):
        fields.SigSeedValueSpec.from_pdf_object(
            fields.SigSeedValueSpec(flags=fields.SigSeedValFlags.V,
                                    sv_dict_version=4).as_pdf_object())
Ejemplo n.º 3
0
def test_field_lock_compat():
    sv = fields.SigSeedValueSpec(flags=fields.SigSeedValFlags.LOCK_DOCUMENT,
                                 lock_document=fields.SeedLockDocument.LOCK)
    meta = signers.PdfSignatureMetadata(field_name='Sig')
    sign_with_sv(sv, meta, add_field_lock=True)

    sv = fields.SigSeedValueSpec(
        flags=fields.SigSeedValFlags.LOCK_DOCUMENT,
        lock_document=fields.SeedLockDocument.DO_NOT_LOCK)
    meta = signers.PdfSignatureMetadata(field_name='Sig')
    with pytest.raises(SigningError):
        sign_with_sv(sv, meta, add_field_lock=True)
Ejemplo n.º 4
0
def test_sv_mdp_type():
    sv_dict = fields.SigSeedValueSpec().as_pdf_object()
    assert '/MDP' not in sv_dict
    sv_dict = fields.SigSeedValueSpec(
        seed_signature_type=fields.SeedSignatureType(None)).as_pdf_object()
    assert sv_dict['/MDP'] == generic.DictionaryObject(
        {pdf_name('/P'): generic.NumberObject(0)})
    sv_dict = fields.SigSeedValueSpec(
        seed_signature_type=fields.SeedSignatureType(
            fields.MDPPerm.NO_CHANGES)).as_pdf_object()
    assert sv_dict['/MDP'] == generic.DictionaryObject(
        {pdf_name('/P'): generic.NumberObject(1)})

    sv_spec = fields.SigSeedValueSpec.from_pdf_object(
        generic.DictionaryObject({
            pdf_name('/MDP'):
            generic.DictionaryObject({pdf_name('/P'): generic.NumberObject(0)})
        }))
    assert sv_spec.seed_signature_type == fields.SeedSignatureType(None)

    sv_spec = fields.SigSeedValueSpec.from_pdf_object(
        generic.DictionaryObject({
            pdf_name('/MDP'):
            generic.DictionaryObject({pdf_name('/P'): generic.NumberObject(2)})
        }))
    assert sv_spec.seed_signature_type == fields.SeedSignatureType(
        fields.MDPPerm.FILL_FORMS)

    with pytest.raises(SigningError):
        fields.SigSeedValueSpec.from_pdf_object(
            generic.DictionaryObject({
                pdf_name('/MDP'):
                generic.DictionaryObject(
                    {pdf_name('/P'): generic.NumberObject(5)})
            }))
    with pytest.raises(SigningError):
        fields.SigSeedValueSpec.from_pdf_object(
            generic.DictionaryObject({
                pdf_name('/MDP'):
                generic.DictionaryObject(
                    {pdf_name('/P'): generic.NullObject()})
            }))
    with pytest.raises(SigningError):
        fields.SigSeedValueSpec.from_pdf_object(
            generic.DictionaryObject(
                {pdf_name('/MDP'): generic.DictionaryObject()}))
    with pytest.raises(SigningError):
        fields.SigSeedValueSpec.from_pdf_object(
            generic.DictionaryObject({pdf_name('/MDP'): generic.NullObject()}))
Ejemplo n.º 5
0
def test_sv_sign_md_req():
    sv = fields.SigSeedValueSpec(
        flags=fields.SigSeedValFlags.DIGEST_METHOD,
        digest_methods=['sha256', 'sha512'],
    )
    with pytest.raises(SigningError):
        sign_with_sv(
            sv, signers.PdfSignatureMetadata(
                md_algorithm='sha1', field_name='Sig'
            )
        )
    sign_with_sv(
        sv, signers.PdfSignatureMetadata(md_algorithm='sha1', field_name='Sig'),
        test_violation=True
    )
    emb_sig = sign_with_sv(
        sv, signers.PdfSignatureMetadata(field_name='Sig')
    )
    assert emb_sig.md_algorithm == 'sha256'
    emb_sig = sign_with_sv(
        sv, signers.PdfSignatureMetadata(
            md_algorithm='sha512', field_name='Sig'
        )
    )
    assert emb_sig.md_algorithm == 'sha512'
Ejemplo n.º 6
0
def test_sv_no_lock_certify():
    sv = fields.SigSeedValueSpec(
        flags=fields.SigSeedValFlags.LOCK_DOCUMENT,
        lock_document=fields.SeedLockDocument.DO_NOT_LOCK)
    meta = signers.PdfSignatureMetadata(
        field_name='Sig',
        certify=True,
        docmdp_permissions=fields.MDPPerm.FILL_FORMS)
    sign_with_sv(sv, meta)

    meta = signers.PdfSignatureMetadata(
        field_name='Sig',
        certify=True,
        docmdp_permissions=fields.MDPPerm.ANNOTATE)
    sign_with_sv(sv, meta)

    meta = signers.PdfSignatureMetadata(
        field_name='Sig',
        certify=True,
    )
    sign_with_sv(sv, meta)

    meta = signers.PdfSignatureMetadata(field_name='Sig')
    sign_with_sv(sv, meta)

    meta = signers.PdfSignatureMetadata(
        field_name='Sig',
        certify=True,
        docmdp_permissions=fields.MDPPerm.NO_CHANGES)
    sign_with_sv(sv, meta, test_violation=True)
Ejemplo n.º 7
0
def test_sv_sign_addrevinfo_req(requests_mock):
    sv = fields.SigSeedValueSpec(flags=fields.SigSeedValFlags.ADD_REV_INFO,
                                 add_rev_info=True)
    vc = live_testing_vc(requests_mock)
    meta = signers.PdfSignatureMetadata(
        field_name='Sig',
        validation_context=vc,
        subfilter=fields.SigSeedSubFilter.ADOBE_PKCS7_DETACHED,
        embed_validation_info=True)
    emb_sig = sign_with_sv(sv, meta)
    status = validate_pdf_ltv_signature(
        emb_sig, RevocationInfoValidationType.ADOBE_STYLE,
        {'trust_roots': TRUST_ROOTS})
    assert status.valid and status.trusted
    assert emb_sig.sig_object['/SubFilter'] == '/adbe.pkcs7.detached'

    meta = signers.PdfSignatureMetadata(
        field_name='Sig',
        validation_context=vc,
        subfilter=fields.SigSeedSubFilter.ADOBE_PKCS7_DETACHED,
        embed_validation_info=False)
    with pytest.raises(SigningError):
        sign_with_sv(sv, meta)
    sign_with_sv(sv, meta, test_violation=True)
    meta = signers.PdfSignatureMetadata(
        field_name='Sig',
        validation_context=vc,
        subfilter=fields.SigSeedSubFilter.PADES,
        embed_validation_info=True)
    # this shouldn't work with PAdES
    with pytest.raises(SigningError):
        sign_with_sv(sv, meta)
    sign_with_sv(sv, meta, test_violation=True)
Ejemplo n.º 8
0
def test_sv_subfilter_unsupported_partial():
    sv_spec = fields.SigSeedValueSpec(
        flags=fields.SigSeedValFlags.SUBFILTER,
        subfilters=[fields.SigSeedSubFilter.ADOBE_PKCS7_DETACHED, PADES])
    w = IncrementalPdfFileWriter(prepare_sv_field(sv_spec))
    field_name, _, sig_field = next(fields.enumerate_sig_fields(w))
    sig_field = sig_field.get_object()
    sv_ref = sig_field.raw_get('/SV')
    w.mark_update(sv_ref)
    sv_ref.get_object()['/SubFilter'][0] = pdf_name('/this.doesnt.exist')
    out = BytesIO()
    w.write(out)
    out.seek(0)
    frozen = out.getvalue()

    signers.sign_pdf(IncrementalPdfFileWriter(BytesIO(frozen)),
                     signers.PdfSignatureMetadata(field_name='Sig'),
                     signer=FROM_CA,
                     timestamper=DUMMY_TS)
    with pytest.raises(SigningError):
        signers.sign_pdf(
            IncrementalPdfFileWriter(BytesIO(frozen)),
            signers.PdfSignatureMetadata(
                field_name='Sig',
                subfilter=fields.SigSeedSubFilter.ADOBE_PKCS7_DETACHED),
            signer=FROM_CA,
            timestamper=DUMMY_TS)
Ejemplo n.º 9
0
def test_sv_flag_appearance_required():
    sv = fields.SigSeedValueSpec(
        flags=fields.SigSeedValFlags.APPEARANCE_FILTER,
        appearance='test'
    )
    meta = signers.PdfSignatureMetadata(field_name='Sig')
    with pytest.raises(SigningError):
        sign_with_sv(sv, meta)
Ejemplo n.º 10
0
def test_sv_cert_flag_unsupported():
    sv = fields.SigSeedValueSpec(
        cert=fields.SigCertConstraints(
            flags=fields.SigCertConstraintFlags.RESERVED,
        )
    )
    meta = signers.PdfSignatureMetadata(field_name='Sig')
    with pytest.raises(NotImplementedError):
        sign_with_sv(sv, meta)
Ejemplo n.º 11
0
def test_sv_sign_cert_constraint():
    # this is more thoroughly unit tested at a lower level (see further up),
    # so we simply try two basic scenarios here for now
    from asn1crypto import x509
    sv = fields.SigSeedValueSpec(cert=fields.SigCertConstraints(
        flags=fields.SigCertConstraintFlags.SUBJECT_DN,
        subject_dn=x509.Name.build({'common_name': 'Lord Testerino'}),
    ))
    sign_with_sv(sv, signers.PdfSignatureMetadata(field_name='Sig'))
    sv = fields.SigSeedValueSpec(cert=fields.SigCertConstraints(
        flags=fields.SigCertConstraintFlags.SUBJECT_DN,
        subject_dn=x509.Name.build({'common_name': 'Not Lord Testerino'}),
    ))
    with pytest.raises(SigningError):
        sign_with_sv(sv, signers.PdfSignatureMetadata(field_name='Sig'))
    sign_with_sv(sv,
                 signers.PdfSignatureMetadata(field_name='Sig'),
                 test_violation=True)
Ejemplo n.º 12
0
def test_sv_flag_unsupported():
    sv = fields.SigSeedValueSpec(
        flags=(fields.SigSeedValFlags.LEGAL_ATTESTATION
               | fields.SigSeedValFlags.APPEARANCE_FILTER),
        legal_attestations=['abc'],
        appearance='test')
    meta = signers.PdfSignatureMetadata(field_name='Sig')
    with pytest.raises(NotImplementedError):
        sign_with_sv(sv, meta, test_violation=True)
Ejemplo n.º 13
0
def test_sv_mdp_must_certify_wrong_docmdp():

    sv = fields.SigSeedValueSpec(seed_signature_type=fields.SeedSignatureType(
        fields.MDPPerm.FILL_FORMS), )
    meta = signers.PdfSignatureMetadata(
        field_name='Sig',
        certify=True,
        docmdp_permissions=fields.MDPPerm.NO_CHANGES)
    with pytest.raises(SigningError):
        sign_with_sv(sv, meta)
Ejemplo n.º 14
0
def test_sv_sign_subfilter_hint():
    sv = fields.SigSeedValueSpec(subfilters=[PADES])
    emb_sig = sign_with_sv(
        sv,
        signers.PdfSignatureMetadata(
            md_algorithm='sha1',
            field_name='Sig',
            subfilter=fields.SigSeedSubFilter.ADOBE_PKCS7_DETACHED))
    assert emb_sig.sig_object['/SubFilter'] == '/adbe.pkcs7.detached'
    emb_sig = sign_with_sv(sv, signers.PdfSignatureMetadata(field_name='Sig'))
    assert emb_sig.sig_object['/SubFilter'] == PADES.value
Ejemplo n.º 15
0
def test_sv_sign_md_hint():
    sv = fields.SigSeedValueSpec(digest_methods=['sha256', 'sha512'])
    emb_sig = sign_with_sv(
        sv, signers.PdfSignatureMetadata(md_algorithm='sha1',
                                         field_name='Sig'))
    assert emb_sig.md_algorithm == 'sha1'
    emb_sig = sign_with_sv(sv, signers.PdfSignatureMetadata(field_name='Sig'))
    assert emb_sig.md_algorithm == 'sha256'
    emb_sig = sign_with_sv(
        sv,
        signers.PdfSignatureMetadata(md_algorithm='sha512', field_name='Sig'))
    assert emb_sig.md_algorithm == 'sha512'
Ejemplo n.º 16
0
def test_sv_mdp_no_certify():

    sv = fields.SigSeedValueSpec(
        seed_signature_type=fields.SeedSignatureType(), )
    meta = signers.PdfSignatureMetadata(field_name='Sig')
    sign_with_sv(sv, meta)

    meta = signers.PdfSignatureMetadata(field_name='Sig', certify=True)
    with pytest.raises(SigningError):
        sign_with_sv(sv, meta)

    meta = signers.PdfSignatureMetadata(field_name='Sig', certify=True)
    sign_with_sv(sv, meta, test_violation=True)
Ejemplo n.º 17
0
def test_sv_sign_reason_prohibited(reasons_param):
    sv = fields.SigSeedValueSpec(flags=fields.SigSeedValFlags.REASONS,
                                 reasons=reasons_param)
    aw_yiss = signers.PdfSignatureMetadata(reason='Aw yiss', field_name='Sig')
    with pytest.raises(SigningError):
        sign_with_sv(sv, aw_yiss)
    sign_with_sv(sv, aw_yiss, test_violation=True)

    dot = signers.PdfSignatureMetadata(reason='.', field_name='Sig')
    with pytest.raises(SigningError):
        sign_with_sv(sv, dot)
    sign_with_sv(sv, dot, test_violation=True)

    emb_sig = sign_with_sv(sv, signers.PdfSignatureMetadata(field_name='Sig'))
    assert pdf_name('/Reason') not in emb_sig.sig_object
Ejemplo n.º 18
0
def test_sv_sign_reason_req():
    sv = fields.SigSeedValueSpec(flags=fields.SigSeedValFlags.REASONS,
                                 reasons=['I agree', 'Works for me'])
    aw_yiss = signers.PdfSignatureMetadata(reason='Aw yiss', field_name='Sig')
    with pytest.raises(SigningError):
        sign_with_sv(sv, aw_yiss)
    sign_with_sv(sv, aw_yiss, test_violation=True)

    with pytest.raises(SigningError):
        sign_with_sv(sv, signers.PdfSignatureMetadata(field_name='Sig'))
    sign_with_sv(sv,
                 signers.PdfSignatureMetadata(field_name='Sig'),
                 test_violation=True)

    emb_sig = sign_with_sv(
        sv, signers.PdfSignatureMetadata(field_name='Sig', reason='I agree'))
    assert emb_sig.sig_object['/Reason'] == 'I agree'
Ejemplo n.º 19
0
def test_sv_timestamp_url(requests_mock):
    # state issues (see comment in signers.py), so create a fresh signer
    sv = fields.SigSeedValueSpec(timestamp_server_url=DUMMY_HTTP_TS.url,
                                 timestamp_required=True)
    meta = signers.PdfSignatureMetadata(field_name='Sig')
    ts_requested = False

    def ts_callback(*args, **kwargs):
        nonlocal ts_requested
        ts_requested = True
        return ts_response_callback(*args, **kwargs)

    requests_mock.post(DUMMY_HTTP_TS.url,
                       content=ts_callback,
                       headers={'Content-Type': 'application/timestamp-reply'})
    # noinspection PyTypeChecker
    sign_with_sv(sv, meta, timestamper=None)
    assert ts_requested
Ejemplo n.º 20
0
def test_sv_sign_subfilter_req():
    sv = fields.SigSeedValueSpec(flags=fields.SigSeedValFlags.SUBFILTER,
                                 subfilters=[PADES])
    with pytest.raises(SigningError):
        sign_with_sv(
            sv,
            signers.PdfSignatureMetadata(
                md_algorithm='sha1',
                field_name='Sig',
                subfilter=fields.SigSeedSubFilter.ADOBE_PKCS7_DETACHED))
    sign_with_sv(sv,
                 signers.PdfSignatureMetadata(
                     md_algorithm='sha1',
                     field_name='Sig',
                     subfilter=fields.SigSeedSubFilter.ADOBE_PKCS7_DETACHED),
                 test_violation=True)
    emb_sig = sign_with_sv(sv, signers.PdfSignatureMetadata(field_name='Sig'))
    assert emb_sig.sig_object['/SubFilter'] == PADES.value
Ejemplo n.º 21
0
def test_append_sig_field_with_simple_sv():
    w = IncrementalPdfFileWriter(BytesIO(MINIMAL))

    sv = fields.SigSeedValueSpec(
        reasons=['a', 'b', 'c'],
        cert=fields.SigCertConstraints(
            subject_dn=FROM_CA.signing_cert.subject,
            issuers=[INTERM_CERT],
            subjects=[FROM_CA.signing_cert],
            key_usage=[
                fields.SigCertKeyUsage.from_sets(
                    {'digital_signature', 'non_repudiation'},
                    {'key_agreement'})
            ]),
        digest_methods=['ssh256'],
        add_rev_info=True,
        subfilters=[fields.SigSeedSubFilter.ADOBE_PKCS7_DETACHED],
        timestamp_server_url='https://tsa.example.com',
    )
    sp = fields.SigFieldSpec('InvisibleSig', seed_value_dict=sv)
    fields.append_signature_field(w, sp)
    out = BytesIO()
    w.write(out)
    out.seek(0)
    r = PdfFileReader(out)
    _, _, sig_field_ref = next(fields.enumerate_sig_fields(r))
    sv_dict = sig_field_ref.get_object()['/SV']
    assert sv_dict['/V'] == generic.NumberObject(2)
    del sv_dict['/V']
    recovered_sv = fields.SigSeedValueSpec.from_pdf_object(sv_dict)
    # x509.Certificate doesn't have an __eq__ implementation apparently,
    # so for the purposes of the test, we replace them by byte dumps
    issuers1 = recovered_sv.cert.issuers
    issuers2 = sv.cert.issuers
    issuers1[0] = issuers1[0].dump()
    issuers2[0] = issuers2[0].dump()

    subjects1 = recovered_sv.cert.subjects
    subjects2 = sv.cert.subjects
    subjects1[0] = subjects1[0].dump()
    subjects2[0] = subjects2[0].dump()
    assert recovered_sv == sv
Ejemplo n.º 22
0
async def test_add_revinfo_wrong_subfilter():
    sv = fields.SigSeedValueSpec(flags=fields.SigSeedValFlags.ADD_REV_INFO,
                                 add_rev_info=True)

    sig_field_spec = fields.SigFieldSpec(
        sig_field_name='Sig',
        seed_value_dict=sv,
    )

    w = IncrementalPdfFileWriter(BytesIO(MINIMAL))
    fields.append_signature_field(w, sig_field_spec)

    cms_writer = cms_embedder.PdfCMSEmbedder().write_cms(field_name='Sig',
                                                         writer=w)
    next(cms_writer)
    # wrong subfilter: PAdES
    #  but we do embed an (empty) RevInfoArchival attribute
    sig_obj = signers.SignatureObject(bytes_reserved=8192, subfilter=PADES)

    cms_writer.send(cms_embedder.SigObjSetup(sig_placeholder=sig_obj))

    prep_digest, output = cms_writer.send(
        cms_embedder.SigIOSetup(md_algorithm='sha256', in_place=True))
    cms_obj = await FROM_CA.async_sign(
        data_digest=prep_digest.document_digest,
        digest_algorithm='sha256',
        signed_attr_settings=PdfCMSSignedAttributes(
            # empty
            adobe_revinfo_attr=asn1_pdf.RevocationInfoArchival({'ocsp': []})))
    await PdfTBSDocument.async_finish_signing(output, prep_digest, cms_obj)
    r = PdfFileReader(output)
    s = r.embedded_signatures[0]
    status = await async_validate_pdf_signature(s, dummy_ocsp_vc())
    summary = status.pretty_print_details()
    assert status.intact and status.valid
    assert 'not satisfy the SV constraints' in summary
    assert 'requires subfilter' in status.seed_value_constraint_error.args[0]
    assert not status.seed_value_ok