def test_sign_crypt_aes256(password):
    w = IncrementalPdfFileWriter(BytesIO(MINIMAL_ONE_FIELD_AES256))
    w.encrypt(password)
    out = signers.sign_pdf(w,
                           signers.PdfSignatureMetadata(),
                           signer=FROM_CA,
                           existing_fields_only=True)

    r = PdfFileReader(out)
    r.decrypt(password)
    s = r.embedded_signatures[0]
    val_trusted(s)
def test_sign_crypt_pubkey_rc4():
    w = IncrementalPdfFileWriter(BytesIO(MINIMAL_PUBKEY_ONE_FIELD_RC4))
    w.encrypt_pubkey(PUBKEY_SELFSIGNED_DECRYPTER)
    out = signers.sign_pdf(w,
                           signers.PdfSignatureMetadata(),
                           signer=FROM_CA,
                           existing_fields_only=True)

    r = PdfFileReader(out)
    r.decrypt_pubkey(PUBKEY_SELFSIGNED_DECRYPTER)
    s = r.embedded_signatures[0]
    val_trusted(s)
Exemplo n.º 3
0
def test_circular_form_tree_sign():
    fname = os.path.join(PDF_DATA_DIR, 'form-tree-circular-ref-input.pdf')
    with open(fname, 'rb') as inf:
        w = IncrementalPdfFileWriter(inf)
        out = signers.sign_pdf(
            w, signature_meta=signers.PdfSignatureMetadata(
                field_name='Sig'
            ), signer=FROM_CA
        )
    r = PdfFileReader(out)
    with pytest.raises(PdfReadError, match='Circular.*form tree'):
        list(r.embedded_signatures)
Exemplo n.º 4
0
def test_sign_with_trust_pkcs12():
    w = IncrementalPdfFileWriter(BytesIO(MINIMAL))
    out = signers.sign_pdf(
        w, signers.PdfSignatureMetadata(field_name='Sig1'),
        signer=FROM_CA_PKCS12
    )
    r = PdfFileReader(out)
    s = r.embedded_signatures[0]
    assert s.field_name == 'Sig1'
    status = val_untrusted(s)
    assert not status.trusted

    val_trusted(s)
Exemplo n.º 5
0
def test_timestamp_wrong_type():
    w = IncrementalPdfFileWriter(BytesIO(MINIMAL))
    meta = signers.PdfSignatureMetadata(field_name='Sig1')
    out = signers.sign_pdf(w, meta, signer=SELF_SIGN)

    r = PdfFileReader(out)
    emb = r.embedded_signatures[0]
    # Again:
    # (yes, obviously this also isn't a valid timestamp token, hence the
    #  match=... rule here)
    with pytest.raises(SignatureValidationError,
                       match='.*must be /DocTimeStamp.*'):
        validate_pdf_timestamp(emb, validation_context=SIMPLE_V_CONTEXT())
Exemplo n.º 6
0
def test_sign_reject_freed(forbid_freeing):

    w = IncrementalPdfFileWriter(BytesIO(MINIMAL_ONE_FIELD))
    out = signers.sign_pdf(
        w,
        signature_meta=signers.PdfSignatureMetadata(field_name='Sig1'),
        signer=FROM_CA)

    # free the ref containing the /Info dictionary
    # since we don't have support for freeing objects in the writer (yet),
    # do it manually
    r = PdfFileReader(out)
    last_startxref = r.last_startxref

    # NOTE the linked list offsets are dummied out, but our Xref parser
    # doesn't care
    len_out = out.seek(0, os.SEEK_END)
    out.write(b'\n'.join([
        b'xref', b'0 1', b'0000000000 65535 f ', b'2 1',
        b'0000000000 00001 f ',
        b'trailer<</Prev %d>>' % last_startxref, b'startxref',
        b'%d' % len_out, b'%%EOF'
    ]))
    r = PdfFileReader(out)
    last_rev = r.xrefs.xref_sections - 1
    some_ref = generic.Reference(2, 0)

    assert some_ref in r.xrefs.refs_freed_in_revision(last_rev)

    sig = r.embedded_signatures[0]
    assert sig.signed_revision == 2

    # make a dummy rule that whitelists our freed object ref

    class AdHocRule(QualifiedWhitelistRule):
        def apply_qualified(self, old: HistoricalResolver,
                            new: HistoricalResolver):
            yield ModificationLevel.LTA_UPDATES, ReferenceUpdate(
                some_ref, paths_checked=RawPdfPath('/Root', '/Pages'))

    val_status = validate_pdf_signature(
        sig,
        SIMPLE_V_CONTEXT(),
        diff_policy=StandardDiffPolicy(DEFAULT_DIFF_POLICY.global_rules +
                                       [AdHocRule()],
                                       DEFAULT_DIFF_POLICY.form_rule,
                                       reject_object_freeing=forbid_freeing))
    if forbid_freeing:
        assert val_status.modification_level == ModificationLevel.OTHER
    else:
        assert val_status.modification_level == ModificationLevel.LTA_UPDATES
Exemplo n.º 7
0
def test_add_revinfo_timestamp_separate_no_dss(requests_mock, with_vri):
    buf = BytesIO(MINIMAL)
    w = IncrementalPdfFileWriter(buf)

    # create signature & timestamp without revocation info
    with freeze_time('2020-11-01'):
        signers.sign_pdf(
            w, signers.PdfSignatureMetadata(field_name='Sig1'),
            signer=FROM_CA, in_place=True
        )
        signers.PdfTimeStamper(timestamper=DUMMY_TS).timestamp_pdf(
            IncrementalPdfFileWriter(buf), 'sha256', in_place=True
        )

    # fast forward 1 month
    with freeze_time('2020-12-01'):
        vc = live_testing_vc(requests_mock)
        r = PdfFileReader(buf)
        emb_sig = r.embedded_signatures[0]
        add_validation_info(emb_sig, vc, in_place=True, add_vri_entry=with_vri)

        r = PdfFileReader(buf)
        emb_sig = r.embedded_signatures[0]

        # without retroactive revinfo, the validation should fail
        status = validate_pdf_ltv_signature(
            emb_sig, RevocationInfoValidationType.PADES_LT,
            {'trust_roots': TRUST_ROOTS}
        )
        assert status.valid and not status.trusted

        # with retroactive revinfo, it should be OK
        status = validate_pdf_ltv_signature(
            emb_sig, RevocationInfoValidationType.PADES_LT,
            {'trust_roots': TRUST_ROOTS, 'retroactive_revinfo': True}
        )
        assert status.valid and status.trusted
        assert status.modification_level == ModificationLevel.LTA_UPDATES
Exemplo n.º 8
0
def test_simple_sign_legacy_signer_upgrade():
    w = IncrementalPdfFileWriter(BytesIO(MINIMAL))
    meta = signers.PdfSignatureMetadata(field_name='Sig1')
    legacy_signer = LegacyRSASigner(
        signing_cert=SELF_SIGN.signing_cert,
        signing_key=SELF_SIGN.signing_key,
        cert_registry=SELF_SIGN.cert_registry,
    )
    out = signers.sign_pdf(w, meta, signer=legacy_signer)

    r = PdfFileReader(out)
    emb = r.embedded_signatures[0]
    assert emb.field_name == 'Sig1'
    val_untrusted(emb)
Exemplo n.º 9
0
def test_adobe_revinfo_live(requests_mock):
    w = IncrementalPdfFileWriter(BytesIO(MINIMAL_ONE_FIELD))
    vc = live_testing_vc(requests_mock)
    out = signers.sign_pdf(
        w, signers.PdfSignatureMetadata(
            field_name='Sig1', validation_context=vc,
            subfilter=fields.SigSeedSubFilter.ADOBE_PKCS7_DETACHED,
            embed_validation_info=True
        ), signer=FROM_CA, timestamper=DUMMY_TS
    )
    r = PdfFileReader(out)
    rivt_adobe = RevocationInfoValidationType.ADOBE_STYLE
    status = validate_pdf_ltv_signature(r.embedded_signatures[0], rivt_adobe, {'trust_roots': TRUST_ROOTS})
    assert status.valid and status.trusted
def test_sign_crypt_rc4_new(password, file):
    w = IncrementalPdfFileWriter(BytesIO(sign_crypt_rc4_files[file]))
    w.encrypt(password)
    out = signers.sign_pdf(
        w,
        signers.PdfSignatureMetadata(field_name='SigNew'),
        signer=FROM_CA,
    )
    out.seek(0)
    r = PdfFileReader(out)
    r.decrypt(password)

    s = r.embedded_signatures[0]
    val_trusted(s)
Exemplo n.º 11
0
def test_sign_with_indir_annots():
    with open(PDF_DATA_DIR + '/minimal-one-field-indir-annots.pdf', 'rb') as f:
        w = IncrementalPdfFileWriter(f)
        out = signers.sign_pdf(
            w, signers.PdfSignatureMetadata(field_name='SigNew'), signer=FROM_CA
        )
        r = PdfFileReader(out)
        e = r.embedded_signatures[0]
        assert e.field_name == 'SigNew'
        val_trusted(e)

        annots_ref = r.root['/Pages']['/Kids'][0].raw_get('/Annots')
        assert isinstance(annots_ref, generic.IndirectObject)
        assert len(annots_ref.get_object()) == 2
Exemplo n.º 12
0
def test_sign_weak_digest():
    w = IncrementalPdfFileWriter(BytesIO(MINIMAL))
    meta = signers.PdfSignatureMetadata(field_name='Sig1', md_algorithm='md5')
    out = signers.sign_pdf(w, meta, signer=FROM_CA)

    r = PdfFileReader(out)
    emb = r.embedded_signatures[0]
    assert emb.field_name == 'Sig1'
    with pytest.raises(WeakHashAlgorithmError):
        val_trusted(emb)

    lenient_vc = ValidationContext(trust_roots=[ROOT_CERT],
                                   weak_hash_algos=set())
    val_trusted(emb, vc=lenient_vc)
Exemplo n.º 13
0
def test_dummy_timestamp():
    w = IncrementalPdfFileWriter(BytesIO(MINIMAL_ONE_FIELD))

    out = signers.sign_pdf(
        w, signers.PdfSignatureMetadata(), signer=FROM_CA, timestamper=DUMMY_TS,
        existing_fields_only=True,
    )

    r = PdfFileReader(out)
    s = r.embedded_signatures[0]
    assert s.field_name == 'Sig1'
    validity = val_trusted(s)
    assert validity.timestamp_validity is not None
    assert validity.timestamp_validity.trusted
Exemplo n.º 14
0
def test_double_sign_lock_second():
    # test if the difference analysis correctly processes /Reference
    # on a newly added signature object

    w = IncrementalPdfFileWriter(BytesIO(MINIMAL))
    fields.append_signature_field(w, field_with_lock_sp(True))
    out = signers.sign_pdf(
        w, signers.PdfSignatureMetadata(field_name='SigFirst'), signer=FROM_CA,
    )
    w = IncrementalPdfFileWriter(out)

    # now sign the locked field
    out = signers.sign_pdf(
        w, signers.PdfSignatureMetadata(field_name='SigNew'), signer=FROM_CA,
    )
    r = PdfFileReader(out)
    s = r.embedded_signatures[0]
    val_trusted(s, extd=True)

    s = r.embedded_signatures[1]
    assert len(s.sig_object.get_object()['/Reference']) == 1

    val_trusted(s)
Exemplo n.º 15
0
def test_sign_without_annot():
    with open(PDF_DATA_DIR + '/minimal-annotless.pdf', 'rb') as f:
        w = IncrementalPdfFileWriter(f)
        meta = signers.PdfSignatureMetadata(field_name='Sig1')
        out = signers.sign_pdf(w, meta, signer=FROM_CA)

    r = PdfFileReader(out)
    emb = r.embedded_signatures[0]
    assert emb.field_name == 'Sig1'
    assert '/AP' not in emb.sig_field
    assert '/Rect' not in emb.sig_field
    assert '/Kids' not in emb.sig_field
    assert '/Type' not in emb.sig_field
    val_trusted(emb)
Exemplo n.º 16
0
def test_form_field_postsign_fill():
    w = IncrementalPdfFileWriter(BytesIO(SIMPLE_FORM))

    # sign, then fill
    meta = signers.PdfSignatureMetadata(field_name='Sig1')
    out = signers.sign_pdf(w, meta, signer=FROM_CA)
    w = IncrementalPdfFileWriter(out)
    set_text_field(w, "Some text")
    out = BytesIO()
    w.write(out)

    r = PdfFileReader(out)
    s = r.embedded_signatures[0]
    assert s.field_name == 'Sig1'
    val_trusted(s, extd=True)
Exemplo n.º 17
0
def test_simple_sign_ecdsa(bulk_fetch):

    w = IncrementalPdfFileWriter(BytesIO(MINIMAL))
    meta = signers.PdfSignatureMetadata(field_name='Sig1', md_algorithm='sha1')
    with _simple_sess(token='testecdsa') as sess:
        signer = pkcs11.PKCS11Signer(sess,
                                     'signer',
                                     other_certs_to_pull=default_other_certs,
                                     bulk_fetch=bulk_fetch)
        out = signers.sign_pdf(w, meta, signer=signer)

    r = PdfFileReader(out)
    emb = r.embedded_signatures[0]
    assert emb.field_name == 'Sig1'
    val_trusted(emb, vc=SIMPLE_ECC_V_CONTEXT())
Exemplo n.º 18
0
def test_form_field_in_group_postsign_fill(variant):
    w = IncrementalPdfFileWriter(BytesIO(GROUP_VARIANTS[variant]))

    # sign, then fill
    meta = signers.PdfSignatureMetadata(field_name='Sig1')
    out = signers.sign_pdf(w, meta, signer=FROM_CA)
    w = IncrementalPdfFileWriter(out)
    set_text_field_in_group(w, 0, "Some text")
    out = BytesIO()
    w.write(out)

    r = PdfFileReader(out)
    s = r.embedded_signatures[0]
    assert s.field_name == 'Sig1'
    val_trusted(s, extd=True)
Exemplo n.º 19
0
def test_sign_field_infer():
    w = IncrementalPdfFileWriter(BytesIO(MINIMAL_ONE_FIELD))

    with pytest.raises(SigningError):
        signers.sign_pdf(w, signers.PdfSignatureMetadata(), signer=FROM_CA)

    out = signers.sign_pdf(w,
                           signers.PdfSignatureMetadata(),
                           signer=FROM_CA,
                           existing_fields_only=True)

    r = PdfFileReader(out)
    s = r.embedded_signatures[0]
    assert s.field_name == 'Sig1'
    val_trusted(s)

    w = IncrementalPdfFileWriter(out)

    # shouldn't work now since all fields are taken
    with pytest.raises(SigningError):
        signers.sign_pdf(w,
                         signers.PdfSignatureMetadata(),
                         signer=FROM_CA,
                         existing_fields_only=True)
Exemplo n.º 20
0
def test_name_location():
    w = IncrementalPdfFileWriter(BytesIO(MINIMAL))

    meta = signers.PdfSignatureMetadata(
        field_name='Sig1', name='Bleh', location='Bluh'
    )
    out = signers.sign_pdf(w, meta, signer=SELF_SIGN)

    r = PdfFileReader(out)
    emb = r.embedded_signatures[0]
    assert emb.field_name == 'Sig1'
    val_untrusted(emb)

    assert emb.sig_object['/Name'] == 'Bleh'
    assert emb.sig_object['/Location'] == 'Bluh'
Exemplo n.º 21
0
def test_simple_sign(bulk_fetch, pss):

    w = IncrementalPdfFileWriter(BytesIO(MINIMAL))
    meta = signers.PdfSignatureMetadata(field_name='Sig1')
    with _simple_sess() as sess:
        signer = pkcs11.PKCS11Signer(sess,
                                     'signer',
                                     other_certs_to_pull=default_other_certs,
                                     bulk_fetch=bulk_fetch,
                                     prefer_pss=pss)
        out = signers.sign_pdf(w, meta, signer=signer)

    r = PdfFileReader(out)
    emb = r.embedded_signatures[0]
    assert emb.field_name == 'Sig1'
    val_trusted(emb)
Exemplo n.º 22
0
def test_simple_sign_from_config():

    w = IncrementalPdfFileWriter(BytesIO(MINIMAL))
    meta = signers.PdfSignatureMetadata(field_name='Sig1')
    config = PKCS11SignatureConfig(module_path=pkcs11_test_module,
                                   token_label='testrsa',
                                   cert_label='signer',
                                   user_pin='1234',
                                   other_certs_to_pull=None)

    with PKCS11SigningContext(config) as signer:
        out = signers.sign_pdf(w, meta, signer=signer)

    r = PdfFileReader(out)
    emb = r.embedded_signatures[0]
    assert emb.field_name == 'Sig1'
    val_trusted(emb)
Exemplo n.º 23
0
def test_sign_pss():
    signer = signers.SimpleSigner.load(
        CRYPTO_DATA_DIR + '/selfsigned.key.pem',
        CRYPTO_DATA_DIR + '/selfsigned.cert.pem',
        ca_chain_files=(CRYPTO_DATA_DIR + '/selfsigned.cert.pem',),
        key_passphrase=b'secret', prefer_pss=True
    )
    w = IncrementalPdfFileWriter(BytesIO(MINIMAL))
    meta = signers.PdfSignatureMetadata(field_name='Sig1')
    out = signers.sign_pdf(w, meta, signer=signer)

    r = PdfFileReader(out)
    emb = r.embedded_signatures[0]
    assert emb.field_name == 'Sig1'
    sda: SignedDigestAlgorithm = emb.signer_info['signature_algorithm']
    assert sda.signature_algo == 'rsassa_pss'
    val_untrusted(emb)
Exemplo n.º 24
0
def test_form_field_ft_tamper():
    w = IncrementalPdfFileWriter(BytesIO(SIMPLE_FORM))

    # sign, then fill
    meta = signers.PdfSignatureMetadata(field_name='Sig1')
    out = signers.sign_pdf(w, meta, signer=FROM_CA)
    w = IncrementalPdfFileWriter(out)
    tf = w.root['/AcroForm']['/Fields'][1].get_object()
    tf['/FT'] = pdf_name('/Sig')
    w.update_container(tf)
    out = BytesIO()
    w.write(out)

    r = PdfFileReader(out)
    s = r.embedded_signatures[0]
    assert s.field_name == 'Sig1'
    val_trusted_but_modified(s)
Exemplo n.º 25
0
def test_no_diff_summary():
    w = IncrementalPdfFileWriter(BytesIO(MINIMAL))
    meta = signers.PdfSignatureMetadata(field_name='Sig1')
    out = signers.sign_pdf(w, meta, signer=SELF_SIGN)

    # just do an incremental DSS update
    DocumentSecurityStore.add_dss(
        out, sig_contents=None, certs=(SELF_SIGN.signing_cert,)
    )

    r = PdfFileReader(out)
    emb = r.embedded_signatures[0]
    status = validate_pdf_signature(emb, skip_diff=True)
    assert emb.diff_result is None
    assert status.modification_level is None
    assert not status.docmdp_ok
    assert status.coverage == SignatureCoverageLevel.ENTIRE_REVISION
    assert 'EXTENDED' in status.summary()
Exemplo n.º 26
0
def test_sign_tight_container():
    w = IncrementalPdfFileWriter(BytesIO(MINIMAL))
    meta = signers.PdfSignatureMetadata(
        field_name='Sig1', tight_size_estimates=True
    )
    out = signers.sign_pdf(w, meta, signer=SELF_SIGN)

    r = PdfFileReader(out)
    emb = r.embedded_signatures[0]
    assert emb.field_name == 'Sig1'
    val_untrusted(emb)

    contents_str = emb.pkcs7_content
    ci = cms.ContentInfo({
        'content_type': 'signed_data',
        'content': emb.signed_data
    })
    assert ci.dump() == contents_str
Exemplo n.º 27
0
def test_sign_multiple_cert_sources(bulk_fetch):

    w = IncrementalPdfFileWriter(BytesIO(MINIMAL))
    meta = signers.PdfSignatureMetadata(field_name='Sig1')
    with _simple_sess() as sess:
        signer = pkcs11.PKCS11Signer(sess,
                                     'signer',
                                     other_certs_to_pull=('root', ),
                                     ca_chain=(TESTING_CA.get_cert(
                                         CertLabel('interm')), ),
                                     bulk_fetch=bulk_fetch)
        assert isinstance(signer.cert_registry, SimpleCertificateStore)
        assert len(list(signer.cert_registry)) == 2
        out = signers.sign_pdf(w, meta, signer=signer)

    r = PdfFileReader(out)
    emb = r.embedded_signatures[0]
    assert emb.field_name == 'Sig1'
    val_trusted(emb)
Exemplo n.º 28
0
def test_signer_provided_others_pulled(bulk_fetch):

    w = IncrementalPdfFileWriter(BytesIO(MINIMAL))
    meta = signers.PdfSignatureMetadata(field_name='Sig1')
    with _simple_sess() as sess:
        signer = pkcs11.PKCS11Signer(
            sess,
            'signer',
            ca_chain={
                TESTING_CA.get_cert(CertLabel('root')),
                TESTING_CA.get_cert(CertLabel('interm')),
            },
        )
        out = signers.sign_pdf(w, meta, signer=signer)

    r = PdfFileReader(out)
    emb = r.embedded_signatures[0]
    assert emb.field_name == 'Sig1'
    val_trusted(emb)
Exemplo n.º 29
0
def test_sign_with_explicit_dsa_implied_hash():
    signer = signers.SimpleSigner(
        signing_cert=TESTING_CA_DSA.get_cert(CertLabel('signer1')),
        signing_key=TESTING_CA_DSA.key_set.get_private_key(
            KeyLabel('signer1')),
        cert_registry=SimpleCertificateStore.from_certs(
            [DSA_ROOT_CERT, DSA_INTERM_CERT]),
        # this is not allowed, but the validator should accept it anyway
        signature_mechanism=SignedDigestAlgorithm({'algorithm': 'dsa'}))
    w = IncrementalPdfFileWriter(BytesIO(MINIMAL))
    out = signers.sign_pdf(w,
                           signers.PdfSignatureMetadata(field_name='Sig1'),
                           signer=signer)
    r = PdfFileReader(out)
    s = r.embedded_signatures[0]
    si = s.signer_info
    assert si['signature_algorithm']['algorithm'].native == 'dsa'
    assert s.field_name == 'Sig1'
    val_trusted(s, vc=SIMPLE_DSA_V_CONTEXT())
Exemplo n.º 30
0
def test_signer_pulled_others_provided(bulk_fetch):

    w = IncrementalPdfFileWriter(BytesIO(MINIMAL))
    meta = signers.PdfSignatureMetadata(field_name='Sig1')
    signer_cert = TESTING_CA.get_cert(CertLabel('signer1'))
    with _simple_sess() as sess:
        signer = pkcs11.PKCS11Signer(sess,
                                     key_label='signer',
                                     signing_cert=signer_cert,
                                     bulk_fetch=bulk_fetch,
                                     other_certs_to_pull=default_other_certs)
        out = signers.sign_pdf(w, meta, signer=signer)

    r = PdfFileReader(out)
    emb = r.embedded_signatures[0]
    assert emb.field_name == 'Sig1'
    assert emb.signer_cert.dump() == signer_cert.dump()
    # this will fail if the intermediate cert is not present
    val_trusted(emb)