def get(filename): # Locate document. This sample should not ocntinue if the file is not found. if not os.path.exists(os.path.join(current_app.config['APPDATA_FOLDER'], filename)): # Return "Not found" code. abort(404) return # Get an instance of the PadesTimestamper class, used to timestamp a PDF # file. stamper = PadesTimestamper() # Set PKI default (see utils.py). set_pki_defaults(stamper) # Set the PDF to be timestamped. stamper.set_pdf_from_path(os.path.join(current_app.config['APPDATA_FOLDER'], filename)) # Generate path for output file and add to the stamper. create_app_data() # Guarantees that "app_data" folder exists. output_file = '%s.pdf' % str(uuid.uuid4()) stamper.output_file_path = os.path.join( current_app.config['APPDATA_FOLDER'], output_file) # Add a timestmap to the PDF file. stamper.stamp() # Return the stamped PDF as a downloadable file. return send_from_directory(current_app.config['APPDATA_FOLDER'], output_file)
def index(): # Get an instance of the Authentication class. auth = Authentication() # Set PKI default options (see utils.py). set_pki_defaults(auth) # Start the authentication. Receive as response a AuthStartResult instance # containing the following fields: # - nonce: The nonce to be signed. This value is also used on "complete" # action. # - digest_algorithm: The digest algorithm that will inform the Web PKI # component to compute the signature. result = auth.start() # Render the fields received form start() method as hidden field to be used # on the javascript and on the "complete" step. We pass the nonce as base64 # to be rendered on page. response = make_response( render_template('authentication_express/index.html', nonce=result.nonce, digest_algorithm=result.digest_algorithm)) # The nonce acquired above can only be used for a single authentication # attempt. In order to retry the signature it is necessary to get a new # token. This can be a problem if the user uses the back button of the # browser, since the browser might show a cached page that we rendered # previously, with a now stale token. To prevent this from happening, we # call the method set_no_cache_headers(), which sets HTTP headers to prevent # caching of the page. get_expired_page_headers(response.headers) return response
def start(): """ This method starts the signature. In this sample, it will be called programatically after the user press the "Sign File" button (see method readCertificate() on static/js/signature-start-form.js). """ userfile = None try: # Recover variables from the POST arguments to be used on this step. cert_thumb = request.form['certThumbField'] cert_content = request.form['certContentField'] if request.form['userfileField'] != 'None': userfile = request.form['userfileField'] # Get an instance of the CadesSignatureStarter class, responsible for # receiving the signature elements and start the signature process. signature_starter = CadesSignatureStarter() # Set PKI default options (see utils.py). set_pki_defaults(signature_starter) # Set signature policy. signature_starter.signature_policy = \ standard_signature_policies.PKI_BRAZIL_CADES_ADR_BASICA # Set file to be signed. If the file is a CMS, PKI Express will # recognize that and will co-sign that file. if userfile: signature_starter.set_file_to_sign_from_path( os.path.join(current_app.config['APPDATA_FOLDER'], userfile)) else: signature_starter.set_file_to_sign_from_path(get_sample_doc_path()) # Set Base64-encoded certificate's content to signature starter. signature_starter.set_certificate_from_base64(cert_content) # Set 'encapsulated content' option (default: True). signature_starter.encapsulated_content = True # Start the signature process. Receive as response the following fields: # - to_sign_hash: The hash to be signed. # - digest_algorithm: The digest algorithm that will inform the Web PKI # component to compute the signature. # - transfer_file: A temporary file to be passed to "complete" step. response = signature_starter.start() # Render the field from start() method as hidden fields to be used on # the javascript or on the "complete" step. return render_template('cades_signature/start.html', to_sign_hash=response['toSignHash'], digest_algorithm=response['digestAlgorithm'], transfer_file=response['transferFile'], cert_thumb=cert_thumb, userfile=userfile) except Exception as e: flash(str(e)) return redirect(url_for('cades_signature.index', userfile=userfile))
def attached(file_id1, file_id2): """ This function performs a merge of CAdES signature using PKI Express when both signatures have encapsulated content """ # Get an instance of the CadesSignatureEditor class, responsible for # receiving the files and merge them. signature_editor = CadesSignatureEditor() # Set PKI default options (see utils.py). set_pki_defaults(signature_editor) # Guarantees that "app data" folder exists. create_app_data() # Generate output filename output_file = '%s.p7s' % (str(uuid.uuid4())) # Add both signatures signature_editor.add_cms_file_from_path( os.path.join(current_app.config['APPDATA_FOLDER'], file_id1)) signature_editor.add_cms_file_from_path( os.path.join(current_app.config['APPDATA_FOLDER'], file_id2)) # Set path to output file signature_editor.output_file = os.path.join( current_app.config['APPDATA_FOLDER'], output_file) # Merge files signature_editor.merge() return render_template('merge_cades_express/index.html', output_file=output_file)
def complete(): # Recover variables from the POST arguments to be used on this step. file_id = request.form['id'] transfer_file = request.form['transferFile'] signature = request.form['signature'] # Get an instance of the SignatureFinisher class, responsible for completing # the signature process. signature_finisher = SignatureFinisher() # Set PKI default options (see utils.py). set_pki_defaults(signature_finisher) # Set the file to be signed. It's the same file we use don "start" method. signature_finisher.set_file_to_sign_from_path( get_sample_batch_doc_path(file_id)) # Set the transfer file. signature_finisher.set_transfer_file_from_path(transfer_file) # Set the signature file. signature_finisher.signature = signature # Generate path for output file and add to the signature finisher. create_app_data() # Guarantees that "app data" folder exists. filename = '%s.p7s' % (str(uuid.uuid4())) signature_finisher.output_file = \ join(current_app.config['APPDATA_FOLDER'], filename) # Complete the signature process. signature_finisher.complete() return jsonify(filename)
def index(file_id): # Locate document. This sample should not continue if the file is not found. if not exists(join(current_app.config['APPDATA_FOLDER'], file_id)): return render_template('error.html', msg='File not found') # Get an instance of the PadesTimestamper class, used to timestamp a PDF # file. stamper = PadesTimestamper() # Set PKI default (see utils.py). set_pki_defaults(stamper) # Set the PDF to be timestamped. stamper.set_pdf_from_path(join(current_app.config['APPDATA_FOLDER'], file_id)) # Generate path for output file and add to the stamper. create_app_data() # Guarantees that "app_data" folder exists. output_file = '%s.pdf' % str(uuid.uuid4()) output_file_path = join(current_app.config['APPDATA_FOLDER'], output_file) stamper.output_file_path = output_file_path # Add a timestamp to the PDF file. stamper.stamp() # Return the stamped PDF as a downloadable file. return send_from_directory(current_app.config['APPDATA_FOLDER'], output_file)
def start(): # Recover variables from the POST arguments to be used in this step. file_id = request.form['id'] cert_content = request.form['certContent'] # Get an instance of the CadesSignatureStarter class, responsible for # receiving the signature elements and start the signature process. signature_starter = CadesSignatureStarter() # Set PKI default options (see utils.py). set_pki_defaults(signature_starter) # Set signature policy. signature_starter.signature_policy = \ standard_signature_policies.PKI_BRAZIL_CADES_ADR_BASICA # Set file to be signed based on its ID. signature_starter.set_file_to_sign_from_path( get_sample_batch_doc_path(file_id)) # Set Base64-encoded certificate's content to signature starter. signature_starter.set_certificate_from_base64(cert_content) # Set 'encapsulated content' option (default: True). signature_starter.encapsulated_content = True # Start the signature process. Receive as response the following fields: # - to_sign_hash: The hash to be signed. # - digest_algorithm: The digest algorithm that will inform the Web PKI # component to compute the signature. # - transfer_file: A temporary file to be passed to "complete" step. response = signature_starter.start() return jsonify(response)
def index(file_id): # Verify if the provided userfile exists. file_path = os.path.join(current_app.config['APPDATA_FOLDER'], file_id) if not os.path.exists(file_path): return render_template('error.html', msg='File not found') # Get an instance of the PadesSignatureExplorer class, used to open/validate # PDF signatures. sig_explorer = PadesSignatureExplorer() # Set PKI default options (see utils.py) set_pki_defaults(sig_explorer) # Specify that we want to validate the signatures in the file, not only # inspect them. sig_explorer.validate = True # Set the PDF file to be inspected. sig_explorer.set_signature_file_from_path(file_path) # Call the open() method, which returns the signature file's information. signature = sig_explorer.open() # Render the signature opening page. return render_template('open_pades_express/index.html', signature=signature)
def start(file_id): """ This method starts the signature. In this sample, it will be called programatically after the user press the "Sign File" button (see method readCertificate() on static/js/signature-start-form.js). """ try: # Recover variables from the POST arguments to be used on this step. cert_thumb = request.form['certThumbField'] cert_content = request.form['certContentField'] # Get an instance of the PadesSignatureStarter class, responsible for # receiving the signature elements and start the signature process. signature_starter = PadesSignatureStarter() # Set PKI default options (see utils.py). set_pki_defaults(signature_starter) # Set signature policy. signature_starter.signature_policy = \ standard_signature_policies.PADES_BASIC_WITH_LTV # Set PDF to be signed signature_starter.set_pdf_to_sign_from_path( os.path.join(current_app.config['APPDATA_FOLDER'], file_id)) # Set Base64-encoded certificate's content to signature starter. signature_starter.set_certificate_from_base64(cert_content) # Set a file reference for the stamp file. Note that this file can be # referenced later by "fref://{alias}" at the "url" field on the visual # representation (see static/vr.json or get_visual_representation() # method). signature_starter.add_file_reference('stamp', get_pdf_stamp_path()) # Set the visual representation. We provided a dictionary that # represents the visual representation JSON model. signature_starter.set_visual_representation( PadesVisualElementsExpress.get_visual_representation()) # Start the signature process. Receive as response the following fields: # - to_sign_hash: The hash to be signed. # - digest_algorithm: The digest algorithm that will inform the Web PKI # component to compute the signature. # - transfer_file: A temporary file to be passed to "complete" step. response = signature_starter.start() # Render the field from start() method as hidden field to be used on the # javascript or on the "complete" step. return render_template('pades_signature_express/start.html', cert_thumb=cert_thumb, transfer_file_id=response['transferFile'], to_sign_hash=response['toSignHash'], digest_algorithm=response['digestAlgorithm']) except Exception as e: return render_template('error.html', msg=e)
def index(userfile): try: # Verify if the provided userfile exists. if not os.path.exists( os.path.join(current_app.config['APPDATA_FOLDER'], userfile)): return render_template('error.html', msg='File not found') # Get an instance of the PadesSigner class, responsible for receiving # the signature elements and performing the local signature. signer = PadesSigner() # Set PKI default options (see utils.py). set_pki_defaults(signer) # Set signature policy. signer.signature_policy = \ standard_signature_policies.PADES_BASIC_WITH_LTV # Set PDF to be signed. signer.set_pdf_to_sign_from_path( os.path.join(current_app.config['APPDATA_FOLDER'], userfile)) # The PKCS #12 certificate path. signer.set_pkcs12_from_path( os.path.join(current_app.static_folder, 'Pierre de Fermat.pfx')) # Set the certificate's PIN. signer.cert_password = '******' # Set a file reference for the stamp file. Note that this file can be # referenced later by "fref://{alias}" at the "url" field on the visual # representation (see content/vr.json or get_visual_representation() # method). signer.add_file_reference('stamp', get_pdf_stamp_path()) # Set visual representation. We provide a dictionary that represents the # visual representation JSON model. signer.set_visual_representation(get_visual_representation()) # Generate path for output file and add to signer object. create_app_data() # Guarantees that "app data" folder exists. output_file = '%s.pdf' % (str(uuid.uuid4())) signer.output_file = os.path.join(current_app.config['APPDATA_FOLDER'], output_file) # Perform the signature. signer_cert = signer.sign(get_cert=True) response = make_response( render_template('pades_signature_server_key/index.html', signer_cert=signer_cert, filename=output_file)) response.headers = get_expired_page_headers() return response except Exception as e: return render_template('error.html', msg=e)
def complete(): """ This function completes the signature, it will be called programatically after the Web PKI component perform the signature and submit the form (see method sign() on static/js/signature-complete-form.js). """ userfile = None try: # Recover variables from the POST arguments to be used on this step. transfer_file = request.form['transferFileField'] signature = request.form['signatureField'] if request.form['userfileField'] != 'None': userfile = request.form['userfileField'] # Get an instance of the SignatureFinisher class, responsible for # completing the signature process. signature_finisher = SignatureFinisher() # Set PKI default options (see utils.py). set_pki_defaults(signature_finisher) # Set the file to be signed. It's the same file we used on "start" # method. if userfile: signature_finisher.set_file_to_sign_from_path( os.path.join(current_app.config['APPDATA_FOLDER'], userfile)) else: signature_finisher.set_file_to_sign_from_path( get_sample_doc_path()) # Set the transfer file. signature_finisher.set_transfer_file_from_path(transfer_file) # Set the signature file. signature_finisher.signature = signature # Generate path for output file and add to the signature finisher. create_app_data() # Guarantees that "app data" folder exists. filename = '%s.p7s' % (str(uuid.uuid4())) signature_finisher.output_file = \ os.path.join(current_app.config['APPDATA_FOLDER'], filename) # Complete the signature process. signer_cert = signature_finisher.complete(get_cert=True) return render_template('cades_signature/signature-info.html', signer_cert=signer_cert, filename=filename) except Exception as e: flash(str(e)) return redirect(url_for('cades_signature.index', userfile=userfile))
def index(userfile): try: # Verify if the provided userfile exists. if not os.path.exists( os.path.join(current_app.config['APPDATA_FOLDER'], userfile)): return render_template('error.html', msg='File not found') # Get an instance of the CadesSigner class, responsible for receiving # the signature elements and performing the local signature. signer = CadesSigner() # Set PKI default options (see utils.py). set_pki_defaults(signer) # Set signature policy. signer.signature_policy = \ standard_signature_policies.PKI_BRAZIL_CADES_ADR_BASICA # Set file to be signed. If the file is a CSM, the PKI Express will # recognize that and will co-sign that file. signer.set_file_to_sign_from_path( os.path.join(current_app.config['APPDATA_FOLDER'], userfile)) # The PKCS #12 certificate path. signer.set_pkcs12_from_path( os.path.join(current_app.static_folder, 'Pierre de Fermat.pfx')) # Set the certificate's PIN. signer.cert_password = '******' # Set 'encapsulate content' option (default: True). signer.encapsulated_content = True # Generate path for output file and add to signer object. create_app_data() # Guarantees that "app_data" folder exists. output_file = '%s.p7s' % (str(uuid.uuid4())) signer.output_file = os.path.join(current_app.config['APPDATA_FOLDER'], output_file) # Perform the signature. signer_cert = signer.sign(get_cert=True) response = make_response( render_template('cades_signature_server_key/index.html', signer_cert=signer_cert, filename=output_file)) response.headers = get_expired_page_headers() return response except Exception as e: return render_template('error.html', msg=e)
def start(): """ This method is called asynchronously via AJAX by the batch signature page for each document being signed. It receives the ID of the document and initiates a PAdES signature using PKI Express and returns a JSON with the data needed in the next signature steps (see batch-signature-form.js). """ # Recover variables from the POST arguments to be used in this step. file_id = request.form['id'] cert_content = request.form['certContent'] # Get an instance of the PadesSignatureStarter, responsible for receiving # the signature elements and start the signature process. signature_starter = PadesSignatureStarter() # Set PKI default options (see utils.py). set_pki_defaults(signature_starter) # Set signature policy. signature_starter.signature_policy = \ standard_signature_policies.PADES_BASIC_WITH_LTV # Set PDF to be signed based on its ID. signature_starter.set_pdf_to_sign_from_path( get_sample_batch_doc_path(file_id)) # Set Base64-encoded certificate's content to signature starter. signature_starter.set_certificate_from_base64(cert_content) # Set a file reference for the stamp file. Note that this file can be # referenced later by "fref://{alias}" at the "url" field on the visual # representation (see static/vr.json or get_visual_representation() # method). signature_starter.add_file_reference('stamp', get_pdf_stamp_path()) # Set the visual representation. We provided a dictionary that # represents the visual representation JSON model. signature_starter.set_visual_representation( PadesVisualElementsExpress.get_visual_representation()) # Start the signature process. Receive as response the following fields: # - to_sign_hash: The hash to be signed. # - digest_algorithm: The digest algorithm that will inform the Web PKI # component to compute the signature. # - transfer_file: A temporary file to be passed to "complete" step. response = signature_starter.start() return jsonify(response)
def index(code): # On printer_version_pades_express, we stored the unformatted version of the # verification code (without hyphens), but used the formatted version (with # hyphens) on the printer-friendly PDF. Now, we remove the hyphens before # looking it up. verification_code = parse_verification_code(code) # Get document associated with verification code. file_id = lookup_verification_code(verification_code) if file_id is None: # Invalid code given! # Small delay to slow down brute-force attacks (if you want to be extra # careful you might want to add a CAPTCHA to the process) sleep(2) # Return "Not Found" page. return render_template('error.html', msg='File not found') # Locate document from storage. file_path = os.path.join(current_app.config['APPDATA_FOLDER'], file_id) # Get an instance of the PadesSignatureExplorer class, used to open/validate # PDF signatures. sig_explorer = PadesSignatureExplorer() # Set PKI default options (see utils.py) set_pki_defaults(sig_explorer) # Specify that we want to validate the signatures in the file, not only # inspect them. sig_explorer.validate = True # Set the PDF file to be inspected. sig_explorer.set_signature_file_from_path(file_path) # Call the open() method, which returns the signature file's information. signature = sig_explorer.open() # Render the signature opening page. return render_template('check_pades_express/index.html', signature=signature, file_id=file_id)
def complete(): """ This method is called asynchronously via AJAX by the batch signature page for each document being signed. It completes the CAdES signature using PKI Express and returns a JSON with the saved filename so that the page can render a link to it. """ # Recover variables from the POST arguments to be used on this step. file_id = request.form['id'] transfer_file = request.form['transferFile'] signature = request.form['signature'] # Get an instance of the SignatureFinisher class, responsible for completing # the signature process. signature_finisher = SignatureFinisher() # Set PKI default options (see utils.py). set_pki_defaults(signature_finisher) # Set the file to be signed. It's the same file we use don "start" method. signature_finisher.set_file_to_sign_from_path( get_sample_batch_doc_path(file_id)) # Set the transfer file. signature_finisher.set_transfer_file_from_path(transfer_file) # Set the signature file. signature_finisher.signature = signature # Generate path for output file and add to the signature finisher. create_app_data() # Guarantees that "app data" folder exists. filename = '%s.p7s' % (str(uuid.uuid4())) signature_finisher.output_file = \ os.path.join(current_app.config['APPDATA_FOLDER'], filename) # Complete the signature process. signature_finisher.complete() return jsonify(filename)
def action(): # Retrieve the values necessary to complete the authentication (rendered in # hidden inputs, see authentication/index.html template): # - nonce: The cryptographic nonce encoded as Base64. # - certContent: The content of the certificate, which is being # authenticated encoded as Base64. # - signature: The computed signature encoded as Base64. nonce_base64 = request.form['nonce'] cert_content_base64 = request.form['certContent'] signature_base64 = request.form['signature'] # Get an instance of the Authentication class. auth = Authentication() # Set PKI default options (see utils.py). set_pki_defaults(auth) # Set the nonce. This value is generate on "start" action and passed by a # hidden field. auth.nonce_base64 = nonce_base64 # Set the Base64-encoded certificate content. auth.certificate_base64 = cert_content_base64 # Set the signature. auth.signature_base64 = signature_base64 # Complete the authentication. Receive as response a AuthCompleteResult # instance containing the following fields: # - The certificate information; # - The validation results. result = auth.complete() # Check the authentication result. vr = result.validation_results if not vr.is_valid: # If the Authentication was not successful, we render a page showing # that what went wrong. # The __str__() method of the ValidationResults object can be used to # obtain the checks performed, but the string contains tabs and new line # characters for formatting, which we'll convert to <br>'s and 's. vr_html = str(vr)\ .replace('\n', '<br>')\ .replace('\t', ' ') # Render the authentication failed page # (templates/authentication_express/failed.html) return render_template('authentication_express/failed.html', vr_html=vr_html) # At this point, you have assurance that the certificate is valid. Now, # you'd typically query your database for a user that matches one of the # certificate's fields, such as user_cert.email_address or # user_cert.pki_brazil.cpf (the actual field to be used as key depends on # your application's business logic) and set the user as authenticated # with whatever web security framework your application uses. For # demonstration purposes. we'll just render the user's certificate # information. user_cert = result.certificate # Render the authentication succeeded page # (templates/authentication_express/success.html). return render_template('authentication_express/success.html', user_cert=user_cert)
def complete(): """ This action will complete the authentication process and create a signature using a session token returned by user. Also, we recover the parameter "customState" containing the id of the file that will be signed. """ try: # Recover variables from query parameters. code = request.args.get('code') state = request.args.get('state') # Get an instance of the TrustServiceManager class, responsible for communicating with # PSCs and handling the OAuth flow. manager = TrustServicesManager() # Complete the authentication process, recovering the session info to be used on the # signature and the custom state (fileId). result = manager.complete_auth(code, state) # Recover file id on custom state parameter. file_id = result.custom_state # Verify if the provided file_id exists. file_path = join(current_app.config['APPDATA_FOLDER'], file_id) if not exists(file_path): return render_template('error.html', msg='File not found') # Get an instance of the PadesSigner class, responsible for receiving # the signature elements and performing the local signature. signer = PadesSigner() # Set PKI default options (see utils.py). set_pki_defaults(signer) # Set signature policy. signer.signature_policy = standard_signature_policies.PADES_BASIC_WITH_LTV # Set PDF to be signed. signer.set_pdf_to_sign_from_path(file_path) # Set trust session acquired on the following steps of this sample. signer.trust_service_session = result.session # Set a file reference for the stamp file. Note that this file can be # referenced later by "fref://{alias}" at the "url" field on the visual # representation (see content/vr.json or get_visual_representation() # method). signer.add_file_reference('stamp', get_pdf_stamp_path()) # Set visual representation. We provide a dictionary that represents the # visual representation JSON model. signer.set_visual_representation( PadesVisualElementsExpress.get_visual_representation()) # Generate path for output file and add to signer object. create_app_data() # Guarantees that "app data" folder exists. output_file = '%s.pdf' % (str(uuid.uuid4())) signer.output_file = join(current_app.config['APPDATA_FOLDER'], output_file) # Perform the signature. signer_cert = signer.sign(get_cert=False) response = make_response(render_template( 'pades_cloud_oauth_express/signature-info.html', signed_pdf=output_file)) get_expired_page_headers(response.headers) return response except Exception as e: return render_template('error.html', msg=e)
def generate_printer_friendly_version(pdf_path, verification_code): # The verification code is generated without hyphens to save storage space # and avoid copy-and-paste problems. On the PDF generation, we use the # "formatted" version, with hyphens (which will later be discarded on the # verification page) formatted_verification_code = format_verification_code(verification_code) # Build the verification link from the constant "VERIFICATION_LINK_FORMAT" # (see above) and the formatted verification code. verification_link = VERIFICATION_LINK_FORMAT % formatted_verification_code # 1. Inspect signatures on the uploaded PDF # Get and instance of the PadesSignatureExplorer class, used to # open/validate PDF signatures. sig_explorer = PadesSignatureExplorer() # Set PKI default options (see utils.py). set_pki_defaults(sig_explorer) # Specify that we want to validate the signatures in the file, not only # inspect them. sig_explorer.validate = True # Set the PDF file to be inspected. sig_explorer.set_signature_file_from_path(pdf_path) # Call the open() method, which returns the signature file's information. signature = sig_explorer.open() # 2. Create PDF with the verification information from uploaded PDF. # Get an instance of the PdfMarker class, used to apply marks on the PDF. pdf_marker = PdfMarker() # Set PKI default options (see utils.py). set_pki_defaults(pdf_marker) # Specify the file to be marked. pdf_marker.set_file_from_path(pdf_path) # Build string with joined names of signers (see method get_display_name # below) signer_names_list = [] for signer in signature.signers: signer_names_list.append(get_display_name(signer.certificate)) signer_names = join_strings_pt(signer_names_list) all_pages_message = "This document was digitally signed by %s.\n" \ "To check the signatures, visit %s at %s and inform this code %s." % (signer_names, VERIFICATION_SITE_NAME_WITH_ARTICLE, VERIFICATION_SITE, formatted_verification_code) # PdfHelper is a class from the PKI Express's "fluent API" that helps # creating elements and parameters for the PdfMarker. pdf = PdfHelper() # ICP-Brasil logo on bottom-right corner of every page (except on the page # which will be created at the end of the document) pdf_marker.marks.append(pdf.mark().on_all_pages().on_container( pdf.container().width(1.0).anchor_right(1.0).height(1.0).anchor_bottom( 1.0)).add_element( pdf.image_element().with_opacity(75).with_image_content( get_icp_brasil_logo_content(), "image/png"))) # Summary on bottom margin of every page (except on the page which will be # created at the end of the document) pdf_marker.marks.append(pdf.mark().on_all_pages().on_container( pdf.container().height(2.0).anchor_bottom().var_width().margins( 1.5, 3.5)).add_element(pdf.text_element().with_opacity( 75).add_section_from_text(all_pages_message))) # Summary on right margin of every page (except on the page which will be # created at the end of the document), rotated 90 degrees counterclockwise # (text goes up). pdf_marker.marks.append(pdf.mark().on_all_pages().on_container( pdf.container().width(2.0).anchor_right().var_height().margins( 1.5, 3.5)).add_element( pdf.text_element().rotate_90_counter_clockwise().with_opacity( 75).add_section_from_text(all_pages_message))) # Create a "manifest" mark on a new page added on the end of the document. # We'll add several elements to this mark. manifest_mark = pdf.mark()\ .on_new_page()\ .on_container( pdf.container() .var_width_and_height() .margins(2.54, 2.54)) # We'll keep track of our "vertical offset" as we add elements to the mark. vertical_offset = 0 element_height = 3 # ICP-Brasil logo on the upper-left corner. Using elementHeight as width # because the image is a square. manifest_mark.add_element(pdf.image_element().on_container( pdf.container().height(element_height).anchor_top(vertical_offset). width(element_height).anchor_left()).with_image_content( get_icp_brasil_logo_content(), "image/png")) # QR Code with the verification link on the upper-right corner. Using # elementHeight as width because the image is a square. manifest_mark.add_element(pdf.qr_code_element().on_container( pdf.container().height(element_height).anchor_top( vertical_offset).width(element_height).anchor_right( )).with_qr_code_data(verification_link).draw_quiet_zones()) manifest_mark.add_element(pdf.text_element().on_container( pdf.container().height(element_height).anchor_top( vertical_offset * 0.2).full_width()).align_text_center().add_section( pdf.text_section().with_font_size( NORMAL_FONT_SIZE * 1.6).with_text('SIGNATURE\nCHECK'))) vertical_offset += element_height # Vertical padding. vertical_offset += 1.7 # Header with verification code. element_height = 2 manifest_mark.add_element(pdf.text_element().on_container( pdf.container().height(element_height).anchor_top( vertical_offset).full_width()).align_text_center().add_section( pdf.text_section().with_font_size( NORMAL_FONT_SIZE * 1.2).with_text( "Verification code: %s" % formatted_verification_code))) vertical_offset += element_height # Paragraph saving "this document was signed by the following signers etc" # and mentioning the timezone of the date/times below. element_height = 2.5 manifest_mark.add_element(pdf.text_element().on_container( pdf.container().height(element_height).anchor_top( vertical_offset).full_width() ).add_section(pdf.text_section( ).with_font_size(NORMAL_FONT_SIZE).with_text( "This document was digitally signed by the following signers on the indicated dates (%s):" % TIME_ZONE_DISPLAY_NAME))) vertical_offset += element_height # Iterate signers. for signer in signature.signers: element_height = 1.5 # Green "check" or red "X" icon depending on result of validation for # this signer. manifest_mark.add_element(pdf.image_element().on_container( pdf.container().height(0.5).anchor_top(vertical_offset + 0.2). width(0.5).anchor_left()).with_image_content( get_validation_result_icon(signer.validation_results.is_valid), 'image/png')) # Description of signer (see method get_signer_description() below). manifest_mark.add_element(pdf.text_element().on_container( pdf.container().height(element_height).anchor_top(vertical_offset). var_width().margins(0.8, 0.0)).add_section( pdf.text_section().with_font_size(NORMAL_FONT_SIZE).with_text( get_signer_description(signer)))) vertical_offset += element_height # Some vertical padding for last signer. vertical_offset += 1.0 # Paragraph with link to verification site and citing both the verification # code above and the verification link below. element_height = 2.5 manifest_mark.add_element(pdf.text_element().on_container( pdf.container().height(element_height).anchor_top( vertical_offset).full_width()).add_section( pdf.text_section().with_font_size(NORMAL_FONT_SIZE).with_text( "In order to check the signatures, visit %s at " % VERIFICATION_SITE_NAME_WITH_ARTICLE) ).add_section( pdf.text_section().with_font_size(NORMAL_FONT_SIZE).with_color( Color.BLUE).with_text(VERIFICATION_SITE) ).add_section( pdf.text_section().with_font_size(NORMAL_FONT_SIZE).with_text( ' and inform the code above or access the link below:'))) vertical_offset += element_height # Verification link. element_height = 1.5 manifest_mark.add_element(pdf.text_element().on_container( pdf.container().height(element_height).anchor_top(vertical_offset). full_width()).add_section( pdf.text_section().with_font_size(NORMAL_FONT_SIZE).with_color( Color.BLUE).with_text(verification_link)).align_text_center()) # Add marks. pdf_marker.marks.append(manifest_mark) # Generate path for output file and add the marker. pfv_filename = "%s.pdf" % str(uuid.uuid4()) pdf_marker.output_file = join(current_app.config['APPDATA_FOLDER'], pfv_filename) # Apply marks. pdf_marker.apply() # Return path for output file. return pfv_filename
def index(file_id): # Verify if the provided "file_id" exists. file_path = join(current_app.config['APPDATA_FOLDER'], file_id) if not exists(file_path): return render_template('error.html', msg='File not found') # Get an instance of the PadesSigner class, responsible for receiving # the signature elements and performing the local signature. signer = PadesSigner() # Set PKI default options (see utils.py). set_pki_defaults(signer) # Set signature policy. signer.signature_policy = standard_signature_policies.PADES_BASIC_WITH_LTV # Set PDF to be signed. signer.set_pdf_to_sign_from_path(file_path) # Set the PKCS #12 certificate path. There is a logic for choosing the generate the PKCS #12 # from "issue certificate" samples or a sample PKCS #12. If no "certId" parameter is passed, # this example will use a default PFX file "Pierre de Fermat.pfx" stored at static/ folder. if request.args.get('certId', None) is None: # The PKCS #12 certificate path. signer.set_pkcs12_from_path(join(current_app.static_folder, 'Pierre de Fermat.pfx')) # Set the certificate's PIN. signer.cert_password = '******' else: # Verify if the provided certId refers to an existing certificate file and key. cert_id = request.args.get('certId', None) if not exists(join(current_app.config['APPDATA_FOLDER'], cert_id)): return render_template('error.html', msg='File not found') # Set generate PKCS #12 and its password signer.set_pkcs12_from_path(join(current_app.config['APPDATA_FOLDER'], cert_id)) signer.cert_password = '******' # Set a file reference for the stamp file. Note that this file can be # referenced later by "fref://{alias}" at the "url" field on the visual # representation (see content/vr.json or get_visual_representation() # method). signer.add_file_reference('stamp', get_pdf_stamp_path()) # Set visual representation. We provide a dictionary that represents the # visual representation JSON model. signer.set_visual_representation( PadesVisualElementsExpress.get_visual_representation()) # Generate path for output file and add to signer object. create_app_data() # Guarantees that "app data" folder exists. output_file = '%s.pdf' % (str(uuid.uuid4())) signer.output_file = join(current_app.config['APPDATA_FOLDER'], output_file) # Perform the signature. signer_cert = signer.sign(get_cert=True) response = make_response(render_template( 'pades_server_key_express/index.html', signer_cert=signer_cert, signed_pdf=output_file)) get_expired_page_headers(response.headers) return response
def authorize(file_id): """" This action is called after the form after the user press the button "Sign". This action will receive the user's CPF and current password. """ try: # Recover variables from the POST arguments. cpf = request.form['cpf'] service = request.form['service'] password = request.form['password'] # Process cpf, removing all formatting. plainCpf = cpf.replace(".", "").replace("-", "") # Get an instance of the TrustServiceManager class, responsible for communicating with # PSCs and handling the password flow. manager = TrustServicesManager() # Complete authentication using CPF and current password. The following method has three sessionTypes: # - SINGLE_SIGNATURE: The returned token can only be used for one single signature request. # - MULTI_SIGNATURE: The returned token can only be used for one multi signature request. # - SIGNATURE_SESSION: The return token can only be used for one or more signature requests. result = manager.password_authorize(service, plainCpf, password, trust_service_session_types.SIGNATURE_SESSION) # Verify if the provided file_id exists. file_path = join(current_app.config['APPDATA_FOLDER'], file_id) if not exists(file_path): return render_template('error.html', msg='File not found') # Get an instance of the PadesSigner class, responsible for receiving # the signature elements and performing the local signature. signer = PadesSigner() # Set PKI default options (see utils.py). set_pki_defaults(signer) # Set signature policy. signer.signature_policy = standard_signature_policies.PADES_BASIC_WITH_LTV # Set PDF to be signed. signer.set_pdf_to_sign_from_path(file_path) # Set trust session acquired on the following steps of this sample. signer.trust_service_session = result.session # Set a file reference for the stamp file. Note that this file can be # referenced later by "fref://{alias}" at the "url" field on the visual # representation (see content/vr.json or get_visual_representation() # method). signer.add_file_reference('stamp', get_pdf_stamp_path()) # Set visual representation. We provide a dictionary that represents the # visual representation JSON model. signer.set_visual_representation( PadesVisualElementsExpress.get_visual_representation()) # Generate path for output file and add to signer object. create_app_data() # Guarantees that "app data" folder exists. output_file = '%s.pdf' % (str(uuid.uuid4())) signer.output_file = join(current_app.config['APPDATA_FOLDER'], output_file) # Perform the signature. signer_cert = signer.sign(get_cert=False) response = make_response(render_template( 'pades_cloud_pwd_express/signature-info.html', signed_pdf=output_file)) get_expired_page_headers(response.headers) return response except Exception as e: return render_template('error.html', msg=e)