def test_pades_double_sign_delete_dss(requests_mock): w = IncrementalPdfFileWriter(BytesIO(MINIMAL_TWO_FIELDS)) meta1 = signers.PdfSignatureMetadata( field_name='Sig1', validation_context=live_testing_vc(requests_mock), subfilter=PADES, embed_validation_info=True, ) meta2 = signers.PdfSignatureMetadata( field_name='Sig2', validation_context=live_testing_vc(requests_mock), subfilter=PADES, embed_validation_info=True, ) out = signers.sign_pdf(w, meta1, signer=FROM_CA, timestamper=DUMMY_TS) w = IncrementalPdfFileWriter(out) out = signers.sign_pdf(w, meta2, signer=FROM_CA, timestamper=DUMMY_TS) w = IncrementalPdfFileWriter(out) # DSS is now covered by the second signature, so this is illegal del w.root['/DSS'] w.update_root() out = BytesIO() w.write(out) r = PdfFileReader(out) assert '/DSS' not in r.root s = r.embedded_signatures[0] assert s.field_name == 'Sig1' val_trusted(s, extd=True) # however, the second signature is violated by the deletion of the /DSS key s = r.embedded_signatures[1] assert s.field_name == 'Sig2' val_trusted_but_modified(s)
def test_double_sig_add_field_annots_indirect(): w = IncrementalPdfFileWriter(BytesIO(MINIMAL_ONE_FIELD)) out = signers.sign_pdf( w, signers.PdfSignatureMetadata( field_name='Sig1', certify=True, docmdp_permissions=fields.MDPPerm.FILL_FORMS), signer=FROM_CA, ) # create a new signature field after signing w = IncrementalPdfFileWriter(out) # ... but first make the /Annots entry of the first page an indirect one first_page = w.root['/Pages']['/Kids'][0] annots_copy = generic.ArrayObject(first_page['/Annots']) first_page['/Annots'] = annots_ref = w.add_object(annots_copy) annots_copy.container_ref = annots_ref w.update_container(first_page) out = signers.sign_pdf(w, signers.PdfSignatureMetadata(field_name='SigNew'), signer=FROM_CA, new_field_spec=fields.SigFieldSpec( sig_field_name='SigNew', box=(10, 10, 10, 10))) r = PdfFileReader(out) s = r.embedded_signatures[0] assert s.field_name == 'Sig1' status = val_trusted(s, extd=True) assert status.modification_level == ModificationLevel.FORM_FILLING assert status.docmdp_ok s = r.embedded_signatures[1] assert s.field_name == 'SigNew' val_trusted(s)
def test_double_sig_fill_deep_field_post_sign(): w = IncrementalPdfFileWriter(BytesIO(MINIMAL_ONE_FIELD)) # create part of the structure already fields._insert_or_get_field_at( w, w.root['/AcroForm']['/Fields'], ('NewSigs', 'NewSig1'), field_obj=fields.SignatureFormField( 'NewSig1', include_on_page=w.root['/Pages']['/Kids'].raw_get(0))) out = signers.sign_pdf(w, signers.PdfSignatureMetadata( field_name='Sig1', certify=True, docmdp_permissions=fields.MDPPerm.FILL_FORMS), signer=FROM_CA, in_place=True) w = IncrementalPdfFileWriter(out) fqn = 'NewSigs.NewSig1' meta = signers.PdfSignatureMetadata(field_name=fqn) out = signers.sign_pdf(w, meta, signer=FROM_CA) r = PdfFileReader(out) s = r.embedded_signatures[0] assert s.field_name == 'Sig1' val_trusted(s, extd=True) s = r.embedded_signatures[1] val_trusted(s)
def test_double_sig_add_visible_field(): w = IncrementalPdfFileWriter(BytesIO(MINIMAL_ONE_FIELD)) out = signers.sign_pdf(w, signers.PdfSignatureMetadata( field_name='Sig1', certify=True, docmdp_permissions=fields.MDPPerm.FILL_FORMS), signer=FROM_CA) # create a new signature field after signing w = IncrementalPdfFileWriter(out) sp = fields.SigFieldSpec('SigNew', box=(10, 74, 140, 134)) fields.append_signature_field(w, sp) out = signers.sign_pdf( w, signers.PdfSignatureMetadata(field_name='SigNew'), signer=FROM_CA, ) r = PdfFileReader(out) s = r.embedded_signatures[0] assert s.field_name == 'Sig1' status = val_trusted(s, extd=True) assert status.modification_level == ModificationLevel.FORM_FILLING assert status.docmdp_ok s = r.embedded_signatures[1] assert s.field_name == 'SigNew' val_trusted(s)
def test_double_sig_add_field(file_ix): w = IncrementalPdfFileWriter(BytesIO(DOUBLE_SIG_TESTDATA_FILES[file_ix])) out = signers.sign_pdf( w, signers.PdfSignatureMetadata( field_name='Sig1', certify=True, docmdp_permissions=fields.MDPPerm.FILL_FORMS), signer=FROM_CA, ) # create a new signature field after signing w = IncrementalPdfFileWriter(out) # throw in an /Info update for good measure dt = generic.pdf_date(datetime(2020, 10, 10, tzinfo=pytz.utc)) info = generic.DictionaryObject({pdf_name('/CreationDate'): dt}) w.set_info(info) out = signers.sign_pdf( w, signers.PdfSignatureMetadata(field_name='SigNew'), signer=FROM_CA, ) r = PdfFileReader(out) s = r.embedded_signatures[0] assert s.field_name == 'Sig1' status = val_trusted(s, extd=True) assert status.modification_level == ModificationLevel.FORM_FILLING assert status.docmdp_ok s = r.embedded_signatures[1] assert s.field_name == 'SigNew' val_trusted(s)
def test_pades_double_sign(requests_mock, certify_first): w = IncrementalPdfFileWriter(BytesIO(MINIMAL_TWO_FIELDS)) meta1 = signers.PdfSignatureMetadata( field_name='Sig1', validation_context=live_testing_vc(requests_mock), subfilter=PADES, embed_validation_info=True, certify=certify_first) meta2 = signers.PdfSignatureMetadata( field_name='Sig2', validation_context=live_testing_vc(requests_mock), subfilter=PADES, embed_validation_info=True, ) out = signers.sign_pdf(w, meta1, signer=FROM_CA, timestamper=DUMMY_TS) w = IncrementalPdfFileWriter(out) out = signers.sign_pdf(w, meta2, signer=FROM_CA, timestamper=DUMMY_TS) r = PdfFileReader(out) s = r.embedded_signatures[0] assert s.field_name == 'Sig1' if certify_first: assert len(s.sig_object['/Reference']) == 1 val_trusted(s, extd=True) s = r.embedded_signatures[1] assert s.field_name == 'Sig2' val_trusted(s, extd=True)
def test_double_signature_tagged_file(): w = IncrementalPdfFileWriter(BytesIO(MINIMAL_TWO_FIELDS_TAGGED)) out = signers.sign_pdf(w, signers.PdfSignatureMetadata( field_name='Sig1', certify=True, docmdp_permissions=fields.MDPPerm.FILL_FORMS), signer=FROM_CA) # create a new signature field after signing w = IncrementalPdfFileWriter(out) out = signers.sign_pdf( w, signers.PdfSignatureMetadata(field_name='Sig2'), signer=FROM_CA, ) r = PdfFileReader(out) s = r.embedded_signatures[0] assert s.field_name == 'Sig1' status = val_trusted(s, extd=True) assert status.modification_level == ModificationLevel.FORM_FILLING assert status.docmdp_ok s = r.embedded_signatures[1] assert s.field_name == 'Sig2' val_trusted(s)
def test_create_deep_sig_field(variant): w = IncrementalPdfFileWriter(BytesIO(GROUP_VARIANTS[variant])) meta = signers.PdfSignatureMetadata(field_name='TextInput.NewSig') out = signers.sign_pdf(w, meta, signer=FROM_CA) r = PdfFileReader(out) s = r.embedded_signatures[0] assert s.field_name == 'TextInput.NewSig' val_trusted(s)
def test_create_multi_deep_sig_field(variant): infile = GROUP_VARIANTS[variant] if variant is not None else MINIMAL w = IncrementalPdfFileWriter(BytesIO(infile)) fqn = 'TextInput.Sigs.Blah.NewSig' meta = signers.PdfSignatureMetadata(field_name=fqn) out = signers.sign_pdf(w, meta, signer=FROM_CA) r = PdfFileReader(out) s = r.embedded_signatures[0] assert s.field_name == fqn val_trusted(s)
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)
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())
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)
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)
def test_no_changes_policy(): w = IncrementalPdfFileWriter(BytesIO(MINIMAL_ONE_FIELD)) out = signers.sign_pdf( w, signers.PdfSignatureMetadata( field_name='Sig1', certify=True, docmdp_permissions=fields.MDPPerm.FILL_FORMS), signer=FROM_CA, ) w = IncrementalPdfFileWriter(out) # do an /Info update dt = generic.pdf_date(datetime(2020, 10, 10, tzinfo=pytz.utc)) info = generic.DictionaryObject({pdf_name('/CreationDate'): dt}) w.set_info(info) w.write_in_place() # check with normal diff policy r = PdfFileReader(out) s = r.embedded_signatures[0] assert s.field_name == 'Sig1' status = val_trusted(s, extd=True) assert status.modification_level == ModificationLevel.LTA_UPDATES assert status.docmdp_ok # now check with the ultra-strict no-op policy r = PdfFileReader(out) s = r.embedded_signatures[0] status = validate_pdf_signature(s, diff_policy=NO_CHANGES_DIFF_POLICY) assert isinstance(s.diff_result, SuspiciousModification) assert not status.docmdp_ok
def test_form_field_postsign_fill_pades_lt(requests_mock): w = IncrementalPdfFileWriter(BytesIO(SIMPLE_FORM)) vc = live_testing_vc(requests_mock) meta = signers.PdfSignatureMetadata( field_name='Sig1', validation_context=vc, subfilter=PADES, embed_validation_info=True, ) # sign, then fill out = signers.sign_pdf(w, meta, signer=FROM_CA, timestamper=DUMMY_TS) 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)
def test_form_field_in_group_locked_postsign_modify_success( field_filled, fieldmdp_spec): # the field that is filled in after signing is always the same, # but the initial one varies w = IncrementalPdfFileWriter(BytesIO(GROUP_VARIANTS[0])) sp = fields.SigFieldSpec('SigNew', box=(10, 74, 140, 134), field_mdp_spec=fieldmdp_spec, doc_mdp_update_value=fields.MDPPerm.FILL_FORMS) fields.append_signature_field(w, sp) set_text_field_in_group(w, field_filled, "Some text") meta = signers.PdfSignatureMetadata(field_name='SigNew') out = signers.sign_pdf(w, meta, signer=FROM_CA) w = IncrementalPdfFileWriter(out) set_text_field_in_group(w, 1, "Some other text") out = BytesIO() w.write(out) r = PdfFileReader(out) s = r.embedded_signatures[0] assert s.field_name == 'SigNew' val_trusted(s, extd=True)
def test_fieldmdp_all_pades_lta(requests_mock): w = IncrementalPdfFileWriter(BytesIO(MINIMAL)) vc = live_testing_vc(requests_mock) sp = fields.SigFieldSpec( 'SigNew', box=(10, 74, 140, 134), field_mdp_spec=fields.FieldMDPSpec(action=fields.FieldMDPAction.ALL), doc_mdp_update_value=fields.MDPPerm.FILL_FORMS) fields.append_signature_field(w, sp) meta = signers.PdfSignatureMetadata( field_name='SigNew', validation_context=vc, embed_validation_info=True, subfilter=fields.SigSeedSubFilter.PADES, use_pades_lta=True) out = signers.sign_pdf(w, meta, signer=FROM_CA, timestamper=DUMMY_TS) r = PdfFileReader(out) s = r.embedded_signatures[0] assert s.field_name == 'SigNew' status = val_trusted(s, extd=True) assert status.modification_level == ModificationLevel.LTA_UPDATES