def test_write_embedded_string(): w = IncrementalPdfFileWriter(BytesIO(MINIMAL)) with open(NOTO_SERIF_JP, 'rb') as ffile: ga = GlyphAccumulator(w, ffile, font_size=10) # shape the string, just to register the glyphs as used ga.shape('テスト') # ... but we're not going to use the result # hardcoded CIDs cid_hx = '0637062a0639' stream = generic.StreamObject( stream_data=f'BT /FEmb 18 Tf 0 100 Td <{cid_hx}> Tj ET'.encode('ascii') ) stream_ref = w.add_object(stream) w.add_stream_to_page( 0, stream_ref, resources=generic.DictionaryObject({ pdf_name('/Font'): generic.DictionaryObject({ pdf_name('/FEmb'): ga.as_resource() }) }) ) out = BytesIO() w.write(out) out.seek(0) r = PdfFileReader(out) page_obj = r.root['/Pages']['/Kids'][0].get_object() conts = page_obj['/Contents'] assert len(conts) == 2 assert stream_ref.idnum in (c.idnum for c in conts)
def test_embed_with_af(incremental): if incremental: w = IncrementalPdfFileWriter(BytesIO(MINIMAL)) else: r = PdfFileReader(BytesIO(MINIMAL)) w = writer.copy_into_new_writer(r) modified = datetime.now(tz=tzlocal.get_localzone()) created = modified - timedelta(days=1) ef_obj = embed.EmbeddedFileObject.from_file_data( w, data=VECTOR_IMAGE_PDF, params=embed.EmbeddedFileParams(creation_date=created, modification_date=modified)) spec = embed.FileSpec(file_spec_string='vector-test.pdf', embedded_data=ef_obj, description='Embedding test /w assoc file', af_relationship=generic.pdf_name('/Unspecified')) embed.embed_file(w, spec) out = BytesIO() w.write(out) r = PdfFileReader(out) assert r.input_version == (2, 0) emb_lst = r.root['/Names']['/EmbeddedFiles']['/Names'] assert len(emb_lst) == 2 assert emb_lst[0] == 'vector-test.pdf' spec_obj = emb_lst[1] assert '/UF' not in spec_obj assert spec_obj['/AFRelationship'] == '/Unspecified' stream = spec_obj['/EF']['/F'] assert stream.data == VECTOR_IMAGE_PDF assert '/UF' not in spec_obj['/EF'] assert r.root['/AF'].raw_get(0).reference == spec_obj.container_ref
def test_write_embedded_string_objstream(): ffile = ttLib.TTFont(NOTO_SERIF_JP) ga = GlyphAccumulator(ffile) cid_hx, _ = ga.feed_string('テスト') assert cid_hx == '0637062a0639' w = IncrementalPdfFileWriter(BytesIO(MINIMAL_XREF)) obj_stream = w.prepare_object_stream() font_ref = ga.embed_subset(w, obj_stream=obj_stream) stream = generic.StreamObject( stream_data=f'BT /FEmb 18 Tf 0 100 Td <{cid_hx}> Tj ET'.encode( 'ascii')) stream_ref = w.add_object(stream) w.add_stream_to_page(0, stream_ref, resources=generic.DictionaryObject({ pdf_name('/Font'): generic.DictionaryObject( {pdf_name('/FEmb'): font_ref}) })) out = BytesIO() w.write(out) out.seek(0) r = PdfFileReader(out) page_obj = r.root['/Pages']['/Kids'][0].get_object() conts = page_obj['/Contents'] assert len(conts) == 2 assert stream_ref.idnum in (c.idnum for c in conts) assert font_ref.idnum in r.xrefs.in_obj_stream out.seek(0) # attempt to grab the font from the object stream font_ref.pdf = r font = font_ref.get_object() assert font['/Type'] == pdf_name('/Font')
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_delete_signature(): w = IncrementalPdfFileWriter(BytesIO(MINIMAL_TWO_FIELDS)) # first, we simply sign the two fields out = signers.sign_pdf(w, signers.PdfSignatureMetadata(field_name='Sig1'), signer=FROM_CA, existing_fields_only=True) w = IncrementalPdfFileWriter(out) out = signers.sign_pdf(w, signers.PdfSignatureMetadata(field_name='Sig2'), signer=FROM_CA, existing_fields_only=True) # after that, we add an incremental update that deletes the first signature # This should invalidate the remaining one. w = IncrementalPdfFileWriter(out) sig_fields = fields.enumerate_sig_fields(w) field_name, sig_obj, sig_field = next(sig_fields) assert field_name == 'Sig1' del sig_field.get_object()['/V'] w.mark_update(sig_field) out = BytesIO() w.write(out) r = PdfFileReader(out) s = r.embedded_signatures[0] assert s.field_name == 'Sig2' val_trusted_but_modified(s)
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_pages_kids_tamper(bogus_kids, indirectify): w = IncrementalPdfFileWriter(BytesIO(MINIMAL)) # sign, then fill meta = signers.PdfSignatureMetadata(field_name='Sig1') out = signers.sign_pdf(w, meta, signer=FROM_CA) w = IncrementalPdfFileWriter(out) # add an empty sig field to trigger the annotation parsing logic # in the difference analysis tool fields.append_signature_field( w, sig_field_spec=fields.SigFieldSpec(sig_field_name="Extra")) page_root = w.root['/Pages'] if indirectify: bogus_kids = generic.ArrayObject(map(w.add_object, bogus_kids)) if bogus_kids is not None: page_root['/Kids'] = bogus_kids else: del page_root['/Kids'] w.update_container(page_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_update_hybrid_twice(fname): with open(os.path.join(PDF_DATA_DIR, fname), 'rb') as inf: w = IncrementalPdfFileWriter(inf) t_obj = w.trailer['/Info'].raw_get('/Title') assert isinstance(t_obj, generic.IndirectObject) w.objects[(t_obj.generation, t_obj.idnum)] \ = generic.pdf_string('Updated') out = BytesIO() w.write(out) r = PdfFileReader(out) assert r.trailer['/Info']['/Title'] == 'Updated' container_info = r.xrefs.get_xref_container_info(1) assert container_info.xref_section_type == XRefSectionType.HYBRID_MAIN container_info = r.xrefs.get_xref_container_info(2) assert container_info.xref_section_type == XRefSectionType.STANDARD w = IncrementalPdfFileWriter(out) w.add_object(generic.pdf_string('This is an object')) w.write_in_place() r = PdfFileReader(out) assert '/XRefStm' not in r.trailer assert '/XRefStm' not in r.trailer_view assert r.trailer['/Info']['/Title'] == 'Updated' container_info = r.xrefs.get_xref_container_info(1) assert container_info.xref_section_type == XRefSectionType.HYBRID_MAIN container_info = r.xrefs.get_xref_container_info(2) assert container_info.xref_section_type == XRefSectionType.STANDARD container_info = r.xrefs.get_xref_container_info(3) assert container_info.xref_section_type == XRefSectionType.STANDARD
def test_add_stream_to_direct_arr(): w = writer.PdfFileWriter() w.insert_page(simple_page(w, 'Test Test', extra_stream=True)) out = BytesIO() w.write(out) out.seek(0) w = IncrementalPdfFileWriter(out) new_stream = 'BT /F1 18 Tf 0 50 Td (Test2 Test2) Tj ET'.encode('ascii') stream = generic.StreamObject(stream_data=new_stream) stream_ref = w.add_object(stream) w.add_stream_to_page(0, stream_ref) out = BytesIO() w.write(out) out.seek(0) r = PdfFileReader(out) # check if the content stream was added page_obj_ref = r.root['/Pages']['/Kids'].raw_get(0) assert isinstance(page_obj_ref, generic.IndirectObject) page_obj = page_obj_ref.get_object() conts = page_obj['/Contents'] assert len(conts) == 3 assert stream_ref.idnum in (c.idnum for c in conts) # check if resource dictionary is still OK assert '/F1' in page_obj['/Resources']['/Font']
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)
def _stamp_file(input_name: str, output_name: str, style: TextStampStyle, stamp_class, dest_page: int, x: int, y: int, **stamp_kwargs): with open(input_name, 'rb') as fin: pdf_out = IncrementalPdfFileWriter(fin) stamp = stamp_class(writer=pdf_out, style=style, **stamp_kwargs) stamp.apply(dest_page, x, y) with open(output_name, 'wb') as out: pdf_out.write(out)
def test_trailer_update(): w = IncrementalPdfFileWriter(BytesIO(MINIMAL_ONE_FIELD)) dt = generic.pdf_date(datetime.datetime(2020, 10, 10, tzinfo=pytz.utc)) info = generic.DictionaryObject({pdf_name('/CreationDate'): dt}) w.trailer['/Info'] = w.add_object(info) out = BytesIO() w.write(out) r = PdfFileReader(out) assert r.trailer['/Info']['/CreationDate'] == dt
def add_sig_field(infile, outfile, field): with pyhanko_exception_manager(): writer = IncrementalPdfFileWriter(infile) for s in field: name, spec = parse_field_location_spec(s) assert spec is not None fields.append_signature_field(writer, spec) writer.write(outfile) infile.close() outfile.close()
def test_historical_nonexistent_xref_access_nonstrict(): out = BytesIO() with open(NONEXISTENT_XREF_PATH, 'rb') as inf: w = IncrementalPdfFileWriter(inf) pg_dict = w.root['/Pages']['/Kids'][0] del pg_dict['/Bleh'] w.update_container(pg_dict) w.write(out) r = PdfFileReader(out, strict=False) hist_root = r.get_historical_root(0) bad_ref = hist_root['/Pages']['/Kids'][0].raw_get('/Bleh') assert isinstance(bad_ref.get_object(), generic.NullObject)
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_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_append_visible_sig_field(): w = IncrementalPdfFileWriter(BytesIO(MINIMAL)) sp = fields.SigFieldSpec('VisibleSig', box=(10, 0, 50, 8)) fields.append_signature_field(w, sp) assert len(w.root['/AcroForm']['/Fields']) == 1 out = BytesIO() w.write(out) out.seek(0) w = IncrementalPdfFileWriter(out) with pytest.raises(PdfWriteError): fields.append_signature_field(w, sp) w = IncrementalPdfFileWriter(BytesIO(MINIMAL_TWO_FIELDS)) fields.append_signature_field(w, sp) assert len(w.root['/AcroForm']['/Fields']) == 3
def test_historical_nonexistent_xref_access(): out = BytesIO() with open(NONEXISTENT_XREF_PATH, 'rb') as inf: w = IncrementalPdfFileWriter(inf) pg_dict = w.root['/Pages']['/Kids'][0] del pg_dict['/Bleh'] w.update_container(pg_dict) w.write(out) r = PdfFileReader(out) current_state = r.root['/Pages']['/Kids'][0] assert '/Bleh' not in current_state hist_root = r.get_historical_root(0) bad_ref = hist_root['/Pages']['/Kids'][0].raw_get('/Bleh') with pytest.raises(misc.PdfReadError, match='not found.*error in strict mode'): bad_ref.get_object()
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)
def prepare_sv_field(sv_spec, add_field_lock=False): w = IncrementalPdfFileWriter(BytesIO(MINIMAL)) if add_field_lock: sp = fields.SigFieldSpec( 'Sig', seed_value_dict=sv_spec, field_mdp_spec=fields.FieldMDPSpec(fields.FieldMDPAction.INCLUDE, fields=['blah']), doc_mdp_update_value=fields.MDPPerm.NO_CHANGES) else: sp = fields.SigFieldSpec('Sig', seed_value_dict=sv_spec) fields.append_signature_field(w, sp) out = BytesIO() w.write(out) out.seek(0) return out
def test_add_stream(): w = IncrementalPdfFileWriter(BytesIO(MINIMAL)) def stream_data(y): return f'BT /F1 18 Tf 0 {y} Td (Test Test) Tj ET'.encode('ascii') stream = generic.StreamObject(stream_data=stream_data(50)) stream_ref = w.add_object(stream) w.add_stream_to_page(0, stream_ref) out = BytesIO() w.write(out) out.seek(0) r = PdfFileReader(out) # check if the content stream was added page_obj_ref = r.root['/Pages']['/Kids'].raw_get(0) assert isinstance(page_obj_ref, generic.IndirectObject) page_obj = page_obj_ref.get_object() conts = page_obj['/Contents'] assert len(conts) == 2 assert stream_ref.idnum in (c.idnum for c in conts) # check if resource dictionary is still OK assert '/F1' in page_obj['/Resources']['/Font'] # let's try adding a third out.seek(0) w = IncrementalPdfFileWriter(out) stream = generic.StreamObject(stream_data=stream_data(100)) new_stream_ref = w.add_object(stream) w.add_stream_to_page(0, new_stream_ref) out = BytesIO() w.write(out) out.seek(0) r = PdfFileReader(out) # check if the content stream was added page_obj_ref = r.root['/Pages']['/Kids'].raw_get(0) assert isinstance(page_obj_ref, generic.IndirectObject) page_obj = page_obj_ref.get_object() conts = page_obj['/Contents'] assert len(conts) == 3 ids = [c.idnum for c in conts] assert stream_ref.idnum in ids and new_stream_ref.idnum in ids
def test_form_field_kids_tamper(bogus_kids, indirectify): 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() if indirectify: bogus_kids = generic.ArrayObject(map(w.add_object, bogus_kids)) tf['/Kids'] = bogus_kids 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)
def test_form_field_structure_modification(): w = IncrementalPdfFileWriter(BytesIO(SIMPLE_FORM)) meta = signers.PdfSignatureMetadata(field_name='Sig1') out = signers.sign_pdf(w, meta, signer=FROM_CA, timestamper=DUMMY_TS) w = IncrementalPdfFileWriter(out) field_arr = w.root['/AcroForm']['/Fields'] # shallow copy the text field tf = generic.DictionaryObject(field_arr[1].get_object()) tf['/T'] = generic.pdf_string('OtherField') field_arr.append(w.add_object(tf)) w.update_container(field_arr) 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_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
def test_embed_twice(incremental): r = PdfFileReader(BytesIO(MINIMAL)) w = writer.copy_into_new_writer(r) modified = datetime.now(tz=tzlocal.get_localzone()) created = modified - timedelta(days=1) _embed_test(w, fname='vector-test.pdf', ufname='テスト.pdf', data=VECTOR_IMAGE_PDF, created=created, modified=modified) if incremental: out = BytesIO() w.write(out) w = IncrementalPdfFileWriter(out) _embed_test(w, fname='some-other-file.pdf', ufname='テスト2.pdf', data=MINIMAL_AES256, created=created, modified=modified) out = BytesIO() w.write(out) r = PdfFileReader(out) emb_lst = r.root['/Names']['/EmbeddedFiles']['/Names'] assert len(emb_lst) == 4 assert emb_lst[0] == 'vector-test.pdf' spec_obj = emb_lst[1] assert spec_obj['/UF'] == 'テスト.pdf' stream = spec_obj['/EF']['/F'] assert stream.data == VECTOR_IMAGE_PDF assert emb_lst[2] == 'some-other-file.pdf' spec_obj = emb_lst[3] assert spec_obj['/UF'] == 'テスト2.pdf' stream = spec_obj['/EF']['/F'] assert stream.data == MINIMAL_AES256
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)
async def test_embed_signed_attachment(): dt = datetime.fromisoformat('2020-11-01T05:00:00+00:00') signature = await FROM_CA.async_sign_general_data( VECTOR_IMAGE_PDF, 'sha256', PdfCMSSignedAttributes(signing_time=dt) ) w = IncrementalPdfFileWriter(BytesIO(MINIMAL)) signers.embed_payload_with_cms( w, file_spec_string='attachment.pdf', payload=embed.EmbeddedFileObject.from_file_data( w, data=VECTOR_IMAGE_PDF, mime_type='application/pdf', params=embed.EmbeddedFileParams( creation_date=dt, modification_date=dt ) ), cms_obj=signature, file_name='添付ファイル.pdf', file_spec_kwargs={'description': "Signed attachment test"} ) out = BytesIO() w.write(out) r = PdfFileReader(out) emb_lst = r.root['/Names']['/EmbeddedFiles']['/Names'] assert len(emb_lst) == 4 assert emb_lst[0] == 'attachment.pdf' spec_obj = emb_lst[1] assert spec_obj['/UF'] == '添付ファイル.pdf' stream = spec_obj['/EF']['/F'] assert stream.data == VECTOR_IMAGE_PDF assert spec_obj['/RF']['/F'][0] == 'attachment.sig' assert spec_obj['/RF']['/UF'][0] == '添付ファイル.sig' rel_file_ref = spec_obj['/RF']['/F'].raw_get(1).reference assert emb_lst[2] == 'attachment.sig' spec_obj = emb_lst[3] assert spec_obj['/UF'] == '添付ファイル.sig' stream = spec_obj['/EF']['/F'] assert stream.data == signature.dump() assert stream.container_ref == rel_file_ref
def test_write_embedded_string_objstream(): w = IncrementalPdfFileWriter(BytesIO(MINIMAL_XREF)) obj_stream = w.prepare_object_stream() with open(NOTO_SERIF_JP, 'rb') as ffile: ga = GlyphAccumulator(w, ffile, font_size=10, obj_stream=obj_stream) # shape the string, just to register the glyphs as used ga.shape('テスト') # ... but we're not going to use the result # hardcoded CIDs cid_hx = '0637062a0639' font_ref = ga.as_resource() stream = generic.StreamObject( stream_data=f'BT /FEmb 18 Tf 0 100 Td <{cid_hx}> Tj ET'.encode( 'ascii')) stream_ref = w.add_object(stream) w.add_stream_to_page(0, stream_ref, resources=generic.DictionaryObject({ pdf_name('/Font'): generic.DictionaryObject( {pdf_name('/FEmb'): font_ref}) })) out = BytesIO() w.write(out) out.seek(0) r = PdfFileReader(out) page_obj = r.root['/Pages']['/Kids'][0].get_object() conts = page_obj['/Contents'] assert len(conts) == 2 assert stream_ref.idnum in (c.idnum for c in conts) xref_sections = r.xrefs._xref_sections last = xref_sections[len(xref_sections) - 1] assert font_ref.idnum in last.xref_data.xrefs_in_objstm out.seek(0) # attempt to grab the font from the object stream font_ref.pdf = r font = font_ref.get_object() assert font['/Type'] == pdf_name('/Font')
def test_simple_embed(incremental): if incremental: w = IncrementalPdfFileWriter(BytesIO(MINIMAL)) else: r = PdfFileReader(BytesIO(MINIMAL)) w = writer.copy_into_new_writer(r) modified = datetime.now(tz=tzlocal.get_localzone()) created = modified - timedelta(days=1) _embed_test(w, fname='vector-test.pdf', ufname='テスト.pdf', data=VECTOR_IMAGE_PDF, created=created, modified=modified) out = BytesIO() w.write(out) r = PdfFileReader(out) assert r.input_version == (1, 7) emb_lst = r.root['/Names']['/EmbeddedFiles']['/Names'] assert len(emb_lst) == 2 assert emb_lst[0] == 'vector-test.pdf' spec_obj = emb_lst[1] assert spec_obj['/Desc'] == 'Embedding test' assert spec_obj['/UF'] == 'テスト.pdf' stream = spec_obj['/EF']['/F'] assert stream.data == VECTOR_IMAGE_PDF assert stream['/Subtype'] == '/application/pdf' assert stream['/Params']['/CheckSum'] \ == binascii.unhexlify('caaf24354fd2e68c08826d65b309b404') assert generic.parse_pdf_date(stream['/Params']['/ModDate']) == modified assert generic.parse_pdf_date( stream['/Params']['/CreationDate']) == created assert '/AF' not in r.root
def test_tamper_sig_obj(policy, skip_diff): w = IncrementalPdfFileWriter(BytesIO(MINIMAL)) meta = signers.PdfSignatureMetadata(field_name='Sig1') out = signers.sign_pdf(w, meta, signer=FROM_CA) w = IncrementalPdfFileWriter(out) sig_obj = w.prev.embedded_signatures[0].sig_object sig_obj['/Bleh'] = generic.BooleanObject(False) w.update_container(sig_obj) out = BytesIO() w.write(out) r = PdfFileReader(out) emb = r.embedded_signatures[0] status = validate_pdf_signature(emb, diff_policy=policy, skip_diff=skip_diff) if skip_diff: assert emb.diff_result is None assert status.modification_level is None else: assert isinstance(emb.diff_result, SuspiciousModification) assert status.modification_level == ModificationLevel.OTHER