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_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_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)
def test_cert_constraint_composite(requests_mock): vc = live_testing_vc(requests_mock) signer_validation_path = CertificateValidator( FROM_CA.signing_cert, FROM_CA.cert_registry, validation_context=vc).validate_usage(set()) tsa_validation_path = CertificateValidator( DUMMY_TS.tsa_cert, FROM_CA.cert_registry, validation_context=vc).validate_usage(set()) from asn1crypto import x509 scc = fields.SigCertConstraints(flags=fields.SigCertConstraintFlags.ISSUER | fields.SigCertConstraintFlags.SUBJECT_DN, issuers=[INTERM_CERT], subject_dn=x509.Name.build({ 'common_name': 'Lord Testerino', 'country_name': 'BE' })) scc.satisfied_by(FROM_CA.signing_cert, signer_validation_path) with pytest.raises(UnacceptableSignerError): scc.satisfied_by(DUMMY_TS.tsa_cert, tsa_validation_path) from asn1crypto import x509 scc = fields.SigCertConstraints(flags=fields.SigCertConstraintFlags.ISSUER | fields.SigCertConstraintFlags.SUBJECT_DN, issuers=[INTERM_CERT], subject_dn=x509.Name.build({ 'common_name': 'Alice & Bob', 'country_name': 'BE' })) with pytest.raises(UnacceptableSignerError): scc.satisfied_by(FROM_CA.signing_cert, signer_validation_path)
def test_cert_constraint_issuer(requests_mock): vc = live_testing_vc(requests_mock) signer_validation_path = CertificateValidator( FROM_CA.signing_cert, FROM_CA.cert_registry, validation_context=vc).validate_usage(set()) tsa_validation_path = CertificateValidator( DUMMY_TS.tsa_cert, FROM_CA.cert_registry, validation_context=vc).validate_usage(set()) scc = fields.SigCertConstraints(flags=fields.SigCertConstraintFlags.ISSUER, issuers=[ROOT_CERT]) scc.satisfied_by(FROM_CA.signing_cert, signer_validation_path) scc.satisfied_by(DUMMY_TS.tsa_cert, tsa_validation_path) with pytest.raises(UnacceptableSignerError): scc.satisfied_by(FROM_CA.signing_cert, None) scc = fields.SigCertConstraints(flags=fields.SigCertConstraintFlags.ISSUER, issuers=[INTERM_CERT]) scc.satisfied_by(FROM_CA.signing_cert, signer_validation_path) with pytest.raises(UnacceptableSignerError): scc.satisfied_by(DUMMY_TS.tsa_cert, tsa_validation_path) scc = fields.SigCertConstraints( flags=fields.SigCertConstraintFlags.ISSUER, issuers=[INTERM_CERT, SELF_SIGN.signing_cert]) scc.satisfied_by(FROM_CA.signing_cert, signer_validation_path) with pytest.raises(UnacceptableSignerError): scc.satisfied_by(DUMMY_TS.tsa_cert, tsa_validation_path) scc = fields.SigCertConstraints(issuers=[INTERM_CERT]) scc.satisfied_by(FROM_CA.signing_cert, signer_validation_path) scc.satisfied_by(DUMMY_TS.tsa_cert, tsa_validation_path)
def test_pades_dss_object_clobber(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, ) dummy_ref = w.add_object(generic.pdf_string("Hi there")).reference out = signers.sign_pdf(w, meta1, signer=FROM_CA, timestamper=DUMMY_TS) w = IncrementalPdfFileWriter(out) # We're going to reassign the DSS object to another object ID, namely # one that clobbers the dummy_ref object. This should be ample cause # for suspicion. dss = w.root['/DSS'] w.objects[(dummy_ref.generation, dummy_ref.idnum)] = dss w.root['/DSS'] = generic.IndirectObject(idnum=dummy_ref.idnum, generation=dummy_ref.generation, pdf=w) w.update_root() out = BytesIO() w.write(out) r = PdfFileReader(out) s = r.embedded_signatures[0] assert s.field_name == 'Sig1' val_trusted_but_modified(s)
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_pades_dss_object_typing_tamper(requests_mock, bogus_dss): 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, ) out = signers.sign_pdf(w, meta1, signer=FROM_CA, timestamper=DUMMY_TS) out.seek(0) original_out = out.read() # write some bogus reference into the DSS w = IncrementalPdfFileWriter(BytesIO(original_out)) w.root['/DSS'] = w.add_object(bogus_dss) w.update_root() out = BytesIO() w.write(out) r = PdfFileReader(out) s = r.embedded_signatures[0] assert s.field_name == 'Sig1' val_trusted_but_modified(s)
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