def addsig_beid(ctx, infile, outfile, lib, use_auth_cert, slot_no): signature_meta = ctx.obj[Ctx.SIG_META] existing_fields_only = ctx.obj[Ctx.EXISTING_ONLY] timestamp_url = ctx.obj[Ctx.TIMESTAMP_URL] session = beid.open_beid_session(lib, slot_no=slot_no) label = 'Authentication' if use_auth_cert else 'Signature' if timestamp_url is not None: timestamper = HTTPTimeStamper(timestamp_url) else: timestamper = None signer = beid.BEIDSigner(session, label) stamp_url = ctx.obj[Ctx.STAMP_URL] text_params = None if stamp_url is not None: text_params = {'url': stamp_url} with pyhanko_exception_manager(): writer = IncrementalPdfFileWriter(infile) result = signers.PdfSigner( signature_meta, signer=signer, timestamper=timestamper, stamp_style=ctx.obj[Ctx.STAMP_STYLE], new_field_spec=ctx.obj[Ctx.NEW_FIELD_SPEC]).sign_pdf( writer, existing_fields_only=existing_fields_only, appearance_text_params=text_params) buf = result.getbuffer() outfile.write(buf) buf.release() infile.close() outfile.close()
def test_no_email(): # just sign with any cert, don't care about validation etc. # This is simply to test the name generation logic if no email address # is available signer = signers.SimpleSigner.load( CRYPTO_DATA_DIR + '/keys-rsa/tsa.key.pem', CRYPTO_DATA_DIR + '/tsa.cert.pem', ca_chain_files=(), key_passphrase=b'secret' ) meta = signers.PdfSignatureMetadata( field_name='Sig1', ) pdf_signer = signers.PdfSigner( meta, signer=signer, stamp_style=stamp.TextStampStyle( stamp_text='%(signer)s\n%(ts)s', ), ) w = IncrementalPdfFileWriter(BytesIO(MINIMAL_ONE_FIELD)) out = pdf_signer.sign_pdf(w, ) r = PdfFileReader(out) emb = r.embedded_signatures[0] assert emb.field_name == 'Sig1' val_untrusted(emb) ap_data = emb.sig_field['/AP']['/N'].data cn = signer.signing_cert.subject.native['common_name'].encode('ascii') assert cn in ap_data
def test_simple_interrupted_signature(): w = IncrementalPdfFileWriter(BytesIO(MINIMAL)) pdf_signer = signers.PdfSigner( signers.PdfSignatureMetadata(field_name='SigNew'), signer=FROM_CA ) with pytest.deprecated_call(): # noinspection PyDeprecation prep_digest, tbs_document, output = pdf_signer.digest_doc_for_signing(w) md_algorithm = tbs_document.md_algorithm assert tbs_document.post_sign_instructions is None # copy the output to a new buffer, just to make a point new_output = BytesIO() assert isinstance(output, BytesIO) buf = output.getbuffer() new_output.write(buf) buf.release() with pytest.deprecated_call(): # noinspection PyDeprecation PdfTBSDocument.finish_signing( new_output, prep_digest, FROM_CA.sign( prep_digest.document_digest, digest_algorithm=md_algorithm, ), ) r = PdfFileReader(new_output) val_trusted(r.embedded_signatures[0])
async def _job(_i): w = IncrementalPdfFileWriter(BytesIO(MINIMAL)) meta = signers.PdfSignatureMetadata( field_name='Sig1', reason=f"PKCS#11 concurrency test #{_i}!") pdf_signer = signers.PdfSigner(meta, signer) sig_result = await pdf_signer.async_sign_pdf(w, in_place=True) await asyncio.sleep(2) return _i, sig_result
def test_allow_hybrid_sign_validate_fail(): fname = 'minimal-hybrid-xref.pdf' with open(os.path.join(PDF_DATA_DIR, fname), 'rb') as inf: w = IncrementalPdfFileWriter(inf, strict=False) meta = signers.PdfSignatureMetadata(field_name='Sig1') out = signers.PdfSigner(signature_meta=meta, signer=FROM_CA).sign_pdf(w) r = PdfFileReader(out) s = r.embedded_signatures[0] with pytest.raises(SignatureValidationError, match="do not permit.*hybrid"): val_trusted(s)
def test_qr_sign_enforce_url_param(params_value): style = QRStampStyle(stamp_text="Hi, it's\n%(ts)s") signer = signers.PdfSigner( signers.PdfSignatureMetadata(field_name='Sig1'), FROM_CA, stamp_style=style ) w = IncrementalPdfFileWriter(BytesIO(MINIMAL_ONE_FIELD)) with pytest.raises(layout.LayoutError): signer.sign_pdf( w, existing_fields_only=True, appearance_text_params=params_value )
def test_allow_hybrid_sign_validate_allow(): fname = 'minimal-hybrid-xref.pdf' with open(os.path.join(PDF_DATA_DIR, fname), 'rb') as inf: w = IncrementalPdfFileWriter(inf, strict=False) meta = signers.PdfSignatureMetadata(field_name='Sig1') out = signers.PdfSigner(signature_meta=meta, signer=FROM_CA).sign_pdf(w) r = PdfFileReader(out, strict=False) s = r.embedded_signatures[0] vc = SIMPLE_V_CONTEXT() val_status = validate_pdf_signature(s, vc) assert val_status.bottom_line
async def _job(_i): w = IncrementalPdfFileWriter(BytesIO(MINIMAL_ONE_FIELD)) meta = signers.PdfSignatureMetadata( field_name='Sig1', validation_context=vc, subfilter=SigSeedSubFilter.PADES, embed_validation_info=True, use_pades_lta=True, reason=f"Live revinfo concurrency test #{_i}!", ) pdf_signer = signers.PdfSigner(meta, signer, timestamper=timestamper) sig_result = await pdf_signer.async_sign_pdf(w, in_place=True) return _i, sig_result
def generic_sign(*, writer, outfile, signature_meta, signer, timestamper, style, new_field_spec, existing_fields_only, text_params): result = signers.PdfSigner(signature_meta, signer=signer, timestamper=timestamper, stamp_style=style, new_field_spec=new_field_spec).sign_pdf( writer, existing_fields_only=existing_fields_only, appearance_text_params=text_params) buf = result.getbuffer() outfile.write(buf) buf.release() writer.prev.stream.close() outfile.close()
def sign_with_sv(sv_spec, sig_meta, signer=FROM_CA, timestamper=DUMMY_TS, *, test_violation=False, add_field_lock=False): w = IncrementalPdfFileWriter( prepare_sv_field(sv_spec, add_field_lock=add_field_lock) ) pdf_signer = signers.PdfSigner(sig_meta, signer, timestamper=timestamper) pdf_signer._ignore_sv = test_violation out = pdf_signer.sign_pdf(w) r = PdfFileReader(out) s = r.embedded_signatures[0] status = validate_pdf_signature(s, dummy_ocsp_vc()) if test_violation: assert not status.seed_value_ok else: assert status.seed_value_ok return EmbeddedPdfSignature(r, s.sig_field)
def test_simple_qr_sign(): style = QRStampStyle(stamp_text="Hi, it's\n%(ts)s") signer = signers.PdfSigner( signers.PdfSignatureMetadata(field_name='Sig1'), FROM_CA, stamp_style=style ) w = IncrementalPdfFileWriter(BytesIO(MINIMAL_ONE_FIELD)) out = signer.sign_pdf( w, existing_fields_only=True, appearance_text_params={'url': 'https://example.com'} ) r = PdfFileReader(out) s = r.embedded_signatures[0] assert s.field_name == 'Sig1' assert '/QR' in s.sig_field['/AP']['/N']['/Resources']['/XObject'] val_trusted(s)
async def test_simple_sign_from_config_async(bulk_fetch, pss): w = IncrementalPdfFileWriter(BytesIO(MINIMAL)) meta = signers.PdfSignatureMetadata(field_name='Sig1') config = PKCS11SignatureConfig(module_path=pkcs11_test_module, token_label='testrsa', other_certs_to_pull=default_other_certs, bulk_fetch=bulk_fetch, prefer_pss=pss, cert_label='signer', user_pin='1234') async with PKCS11SigningContext(config=config) as signer: pdf_signer = signers.PdfSigner(meta, signer) out = await pdf_signer.async_sign_pdf(w) r = PdfFileReader(out) emb = r.embedded_signatures[0] assert emb.field_name == 'Sig1' await async_val_trusted(emb)
def sign_with_sv(sv_spec, sig_meta, signer=FROM_CA, timestamper=DUMMY_TS, *, test_violation=False, add_field_lock=False): w = IncrementalPdfFileWriter( prepare_sv_field(sv_spec, add_field_lock=add_field_lock) ) pdf_signer = signers.PdfSigner(sig_meta, signer, timestamper=timestamper) pdf_signer._ignore_sv = test_violation out = pdf_signer.sign_pdf(w) r = PdfFileReader(out) s = r.embedded_signatures[0] status = validate_pdf_signature(s, dummy_ocsp_vc()) summary = status.pretty_print_details() if test_violation: assert 'not satisfy the SV constraints' in summary assert not status.seed_value_ok else: assert 'no SV issues' in summary assert status.seed_value_ok return EmbeddedPdfSignature(r, s.sig_field, s.fq_name)
def addsig_simple_signer(signer: signers.SimpleSigner, infile, outfile, timestamp_url, signature_meta, existing_fields_only, style, stamp_url, new_field_spec): with pyhanko_exception_manager(): if timestamp_url is not None: timestamper = HTTPTimeStamper(timestamp_url) else: timestamper = None writer = IncrementalPdfFileWriter(infile) # TODO make this an option higher up the tree # TODO mention filename in prompt if writer.prev.encrypted: pdf_pass = getpass.getpass( prompt='Password for encrypted file: ').encode('utf-8') writer.encrypt(pdf_pass) text_params = None if stamp_url is not None: text_params = {'url': stamp_url} result = signers.PdfSigner( signature_meta, signer=signer, timestamper=timestamper, stamp_style=style, new_field_spec=new_field_spec).sign_pdf( writer, existing_fields_only=existing_fields_only, appearance_text_params=text_params) buf = result.getbuffer() outfile.write(buf) buf.release() infile.close() outfile.close()
def test_allow_hybrid_sign(): fname = 'minimal-hybrid-xref.pdf' with open(os.path.join(PDF_DATA_DIR, fname), 'rb') as inf: w = IncrementalPdfFileWriter(inf, strict=False) meta = signers.PdfSignatureMetadata(field_name='Sig1') signers.PdfSigner(signature_meta=meta, signer=SELF_SIGN).sign_pdf(w)