protected void SubmitButton_Click(object sender, EventArgs e) { // Get an instance of the PadesSignatureFinisher class, responsible for completing the signature process var signatureFinisher = Util.GetRestPkiClient().GetPadesSignatureFinisher(); // Set the token for this signature (rendered in a hidden input field, see the view) signatureFinisher.SetToken((string)ViewState["Token"]); // Call the Finish() method, which finalizes the signature process and returns the signed PDF var signedPdf = signatureFinisher.Finish(); // Get information about the certificate used by the user to sign the file. This method must only be called after // calling the Finish() method. var signerCert = signatureFinisher.GetCertificateInfo(); // At this point, you'd typically store the signed PDF on your database. For demonstration purposes, we'll // store the PDF on the App_Data folder and render a page with a link to download the signed PDF and with the // signer's certificate details. var appDataPath = Server.MapPath("~/App_Data"); if (!Directory.Exists(appDataPath)) { Directory.CreateDirectory(appDataPath); } var id = Guid.NewGuid(); var filename = id + ".pdf"; System.IO.File.WriteAllBytes(Path.Combine(appDataPath, filename), signedPdf); this.SignatureFilename = filename.Replace(".", "_"); // Note: we're passing the filename argument with "." as "_" because of limitations of ASP.NET MVC this.SignerCertificate = signerCert; Server.Transfer("PadesSignatureInfo.aspx"); }
protected void SubmitButton_Click(object sender, EventArgs e) { // Get an instance of the CadesSignatureFinisher2 class, responsible for completing the signature process var signatureFinisher = new CadesSignatureFinisher2(Util.GetRestPkiClient()) { // Set the token for this signature acquired previously Token = (string)ViewState["Token"] }; // Call the Finish() method, which finalizes the signature process and returns a SignatureResult object var result = signatureFinisher.Finish(); // At this point, you'd typically store the signed PDF on your database. For demonstration purposes, we'll // store the PDF on our mock Storage class. // The SignatureResult object has various methods for writing the signature file to a stream (WriteTo()), local file (WriteToFile()), open // a stream to read the content (OpenRead()) and get its contents (GetContent()). For large files, avoid the method GetContent() to avoid // memory allocation issues. string fileId; using (var resultStream = result.OpenRead()) { fileId = StorageMock.Store(resultStream, ".p7s"); } // If you prefer a simpler approach without streams, simply do: //fileId = StorageMock.Store(result.GetContent(), ".pdf"); // What you do at this point is up to you. For demonstration purposes, we'll render a page with a link to // download the signed PDF and with the signer's certificate details. this.SignatureFilename = fileId; this.SignerCertificate = result.Certificate; Server.Transfer("CadesSignatureInfo.aspx"); }
protected void SubmitButton_Click(object sender, EventArgs e) { // Get an instance of the XmlSignatureFinisher class, responsible for completing the signature process var signatureFinisher = new XmlSignatureFinisher(Util.GetRestPkiClient()); // Set the token for this signature (rendered in a hidden input field, see the view) signatureFinisher.SetToken((string)ViewState["Token"]); // Call the Finish() method, which finalizes the signature process and returns the signed XML var cms = signatureFinisher.Finish(); // Get information about the certificate used by the user to sign the file. This method must only be called after // calling the Finish() method. var signerCertificate = signatureFinisher.GetCertificateInfo(); // At this point, you'd typically store the XML on your database. For demonstration purposes, we'll // store the XML on the App_Data folder and render a page with a link to download the CMS and with the // signer's certificate details. var appDataPath = Server.MapPath("~/App_Data"); if (!Directory.Exists(appDataPath)) { Directory.CreateDirectory(appDataPath); } var id = Guid.NewGuid(); var filename = id + ".xml"; File.WriteAllBytes(Path.Combine(appDataPath, filename), cms); this.SignatureFilename = filename; this.SignerCertificate = signerCertificate; Server.Transfer("XmlElementSignatureInfo.aspx"); }
protected void SubmitButton_Click(object sender, EventArgs e) { // Get an instance of the PadesSignatureFinisher2 class, responsible for completing the signature process var signatureFinisher = new PadesSignatureFinisher2(Util.GetRestPkiClient()) { // Set the token for this signature (rendered in a hidden input field, see the view) Token = (string)ViewState["Token"] }; // Call the Finish() method, which finalizes the signature process and returns an object to access the signed PDF var result = signatureFinisher.Finish(); // At this point, you'd typically store the signed PDF on your database. For demonstration purposes, we'll // store the PDF on our mock Storage class string fileId; using (var resultStream = result.OpenRead()) { fileId = StorageMock.Store(resultStream, ".pdf"); } // If you prefer a simpler approach without streams, simply do: // fileId = Storage.Store(result.GetContent(), ".pdf"); // What you do at this point is up to you. For demonstration purposes, we'll render a page with a link to // download the signed PDF and with the signer's certificate details. this.SignatureFilename = fileId; this.SignerCertificate = result.Certificate; Server.Transfer("PadesSignatureInfo.aspx"); }
protected void SubmitButton_Click(object sender, EventArgs e) { // Get the token for this authentication process (rendered in a hidden input field, see the view) var token = (string)ViewState["Token"]; // Get an instance of the Authentication class var auth = Util.GetRestPkiClient().GetAuthentication(); // Call the CompleteWithWebPki() method with the token, which finalizes the authentication process. The call yields a // ValidationResults which denotes whether the authentication was successful or not. var validationResults = auth.CompleteWithWebPki(token); // Check the authentication result if (!validationResults.IsValid) { // If the authentication was not successful, we render a page showing what went wrong this.ValidationResults = validationResults; Server.Transfer("AuthenticationFail.aspx"); return; } // At this point, you have assurance that the certificate is valid according to the TrustArbitrator you // selected when starting the authentication and that the user is indeed the certificate's subject. Now, // you'd typically query your database for a user that matches one of the certificate's fields, such as // userCert.EmailAddress or userCert.PkiBrazil.CPF (the actual field to be used as key depends on your // application's business logic) and set the user ID on the auth cookie. For demonstration purposes, // we'll just render a page showing some of the user's certificate information. this.Certificate = auth.GetCertificate(); Server.Transfer("AuthenticationSuccess.aspx"); }
protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { // Get an instance of the CadesSignatureStarter class, responsible for receiving the signature elements and start the // signature process var signatureStarter = Util.GetRestPkiClient().GetCadesSignatureStarter(); // Set the file to be signed as a byte array signatureStarter.SetContentToSign(Util.GetSampleDocContent()); // Set the signature policy signatureStarter.SetSignaturePolicy(StandardCadesSignaturePolicies.PkiBrazil.AdrBasica); // Optionally, set a SecurityContext to be used to determine trust in the certificate chain //signatureStarter.SetSecurityContext(StandardSecurityContexts.PkiBrazil); // Note: Depending on the signature policy chosen above, setting the security context may be mandatory (this is not // the case for ICP-Brasil policies, which will automatically use the PkiBrazil security context if none is passed) // Optionally, set whether the content should be encapsulated in the resulting CMS. If this parameter is ommitted, // the following rules apply: // - If no CmsToSign is given, the resulting CMS will include the content // - If a CmsToCoSign is given, the resulting CMS will include the content if and only if the CmsToCoSign also includes the content signatureStarter.SetEncapsulateContent(true); // Call the StartWithWebPki() method, which initiates the signature. This yields the token, a 43-character // case-sensitive URL-safe string, which identifies this signature process. We'll use this value to call the // signWithRestPki() method on the Web PKI component (see javascript on the view) and also to complete the signature // on the POST action below (this should not be mistaken with the API access token). var token = signatureStarter.StartWithWebPki(); ViewState["Token"] = token; } }
public static string Complete(string token) { // Get an instance of the PadesSignatureFinisher2 class, responsible for completing the signature process var signatureFinisher = new PadesSignatureFinisher2(Util.GetRestPkiClient()) { // Set the token for this signature acquired previously Token = token }; // Call the Finish() method, which finalizes the signature process and returns an SignatureResult object to access // the signed PDF var result = signatureFinisher.Finish(); // At this point, you'd typically store the signed PDF on your database. For demonstration purposes, we'll // store the PDF on our mock Storage class. // The SignatureResult object has various methods for writing the signature file to a stream (WriteTo()), local file (WriteToFile()), open // a stream to read the content (OpenRead()) and get its contents (GetContent()). For large files, avoid the method GetContent() to avoid // memory allocation issues. string fileId; using (var resultStream = result.OpenRead()) { fileId = StorageMock.Store(resultStream, ".pdf"); } // If you prefer a simpler approach without streams, simply do: //fileId = StorageMock.Store(result.GetContent(), ".pdf"); // Send to the javascript the signed file's id to be referenced on a download link return(fileId); }
protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { // Get an instance of the XmlElementSignatureStarter class, responsible for receiving the signature elements and start the // signature process var signatureStarter = new XmlElementSignatureStarter(Util.GetRestPkiClient()); // Set the XML to be signed, a sample Brazilian fiscal invoice pre-generated signatureStarter.SetXml(Util.GetSampleNFeContent()); // Set the ID of the element to be signed (this ID is present in the invoice above) signatureStarter.SetToSignElementId("NFe35141214314050000662550010001084271182362300"); // Set the signature policy signatureStarter.SetSignaturePolicy(StandardXmlSignaturePolicies.PkiBrazil.NFePadraoNacional); // Optionally, set a SecurityContext to be used to determine trust in the certificate chain. Since we're using the // StandardXmlSignaturePolicies.PkiBrazil.NFePadraoNacional policy, the security context will default to PKI Brazil (ICP-Brasil) //signatureStarter.SetSecurityContext(new Guid("...")); // Note: By changing the SecurityContext above you can accept certificates from a custom security context // Call the StartWithWebPki() method, which initiates the signature. This yields the token, a 43-character // case-sensitive URL-safe string, which identifies this signature process. We'll use this value to call the // signWithRestPki() method on the Web PKI component (see javascript on the view) and also to complete the signature // on the POST action below (this should not be mistaken with the API access token). var token = signatureStarter.StartWithWebPki(); ViewState["Token"] = token; } }
protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { // Get an instance of the PadesSignatureStarter class, responsible for receiving the signature elements and start the // signature process var signatureStarter = new PadesSignatureStarter(Util.GetRestPkiClient()) { // Set the unit of measurement used to edit the pdf marks and visual representations MeasurementUnits = PadesMeasurementUnits.Centimeters, // Set the signature policy SignaturePolicyId = StandardPadesSignaturePolicies.Basic, // Set the security context to be used to determine trust in the certificate chain SecurityContextId = Util.GetSecurityContextId(), // Set a visual representation for the signature (see function below) VisualRepresentation = getVisualRepresentation(), }; /* * Optionally, add marks to the PDF before signing. These differ from the signature visual representation in that * they are actually changes done to the document prior to signing, not binded to any signature. Therefore, any number * of marks can be added, for instance one per page, whereas there can only be one visual representation per signature. * However, since the marks are in reality changes to the PDF, they can only be added to documents which have no previous * signatures, otherwise such signatures would be made invalid by the changes to the document (see property * PadesSignatureStarter.BypassMarksIfSigned). This problem does not occur with signature visual representations. * * We have encapsulated this code in a method to include several possibilities depending on the argument passed. * Experiment changing the argument to see different examples of PDF marks. Once you decide which is best for your case, * you can place the code directly here. */ //signatureStarter.PdfMarks.Add(PadesVisualElements.GetPdfMark(1)); // If the user was redirected here by Upload (signature with file uploaded by user), the "userfile" URL argument // will contain the filename under the "App_Data" folder. Otherwise (signature with server file), we'll sign a sample // document. UserFile = Request.QueryString["userfile"]; if (string.IsNullOrEmpty(UserFile)) { // Set the PDF to be signed as a byte array signatureStarter.SetPdfToSign(Util.GetSampleDocContent()); } else { // Set the path of the file to be signed signatureStarter.SetPdfToSign(Server.MapPath("~/App_Data/" + UserFile)); } // Call the StartWithWebPki() method, which initiates the signature. This yields the token, a 43-character // case-sensitive URL-safe string, which identifies this signature process. We'll use this value to call the // signWithRestPki() method on the Web PKI component (see javascript on the view) and also to complete the signature // on the POST action below (this should not be mistaken with the API access token). var token = signatureStarter.StartWithWebPki(); ViewState["Token"] = token; } }
protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { // Get an instance of the CadesSignatureStarter class, responsible for receiving the signature elements and start the // signature process var signatureStarter = Util.GetRestPkiClient().GetCadesSignatureStarter(); // Set the signature policy signatureStarter.SetSignaturePolicy(StandardCadesSignaturePolicies.PkiBrazil.AdrBasica); // Optionally, set a SecurityContext to be used to determine trust in the certificate chain //signatureStarter.SetSecurityContext(StandardSecurityContexts.PkiBrazil); // Note: Depending on the signature policy chosen above, setting the security context may be mandatory (this is not // the case for ICP-Brasil policies, which will automatically use the PkiBrazil security context if none is passed) // Optionally, set whether the content should be encapsulated in the resulting CMS. If this parameter is ommitted, // the following rules apply: // - If no CmsToSign is given, the resulting CMS will include the content // - If a CmsToCoSign is given, the resulting CMS will include the content if and only if the CmsToCoSign also includes the content signatureStarter.SetEncapsulateContent(true); UserFile = Request.QueryString["userfile"]; CmsFile = Request.QueryString["cmsfile"]; if (!String.IsNullOrEmpty(UserFile)) { // If the user was redirected here by Upload (signature with file uploaded by user), the "userfile" URL argument // will contain the filename under the "App_Data" folder. signatureStarter.SetFileToSign(Server.MapPath("~/App_Data/" + UserFile.Replace("_", "."))); } else if (!String.IsNullOrEmpty(CmsFile)) { /* * If the URL argument "cmsfile" is filled, the user has asked to co-sign a previously signed CMS. We'll set the path to the CMS * to be co-signed, which was perviously saved in the App_Data folder by the POST action on this controller. Note two important things: * * 1. The CMS to be co-signed must be set using the method "SetCmsToCoSign", not the method "SetContentToSign" nor "SetFileToSign" * * 2. Since we're creating CMSs with encapsulated content (see call to SetEncapsulateContent above), we don't need to set the content * to be signed, REST PKI will get the content from the CMS being co-signed. */ signatureStarter.SetCmsToCoSign(Server.MapPath("~/App_Data/" + CmsFile.Replace("_", "."))); } else { // If both userfile and cmsfile are null, this is the "signature with server file" case. We'll set the path of the file to be signed signatureStarter.SetFileToSign(Util.GetSampleDocPath()); } // Call the StartWithWebPki() method, which initiates the signature. This yields the token, a 43-character // case-sensitive URL-safe string, which identifies this signature process. We'll use this value to call the // signWithRestPki() method on the Web PKI component (see javascript on the view) and also to complete the signature // on the POST action below (this should not be mistaken with the API access token). var token = signatureStarter.StartWithWebPki(); ViewState["Token"] = token; } }
private void completeSignature() { string fileId; try { // Get an instance of the PadesSignatureFinisher2 class, responsible for completing the signature process var signatureFinisher = new PadesSignatureFinisher2(Util.GetRestPkiClient()) { // Retrieve the token for this signature stored as hidden field on the initial step (see method startNextSignature()) Token = TokenField.Value }; // Call the Finish() method, which finalizes the signature process and returns an SignatureResult object to access // the signed PDF var result = signatureFinisher.Finish(); // At this point, you'd typically store the signed PDF on your database. For demonstration purposes, we'll // store the PDF on our mock Storage class. // The SignatureResult object has various methods for writing the signature file to a stream (WriteTo()), local file (WriteToFile()), open // a stream to read the content (OpenRead()) and get its contents (GetContent()). For large files, avoid the method GetContent() to avoid // memory allocation issues. using (var resultStream = result.OpenRead()) { fileId = StorageMock.Store(resultStream, ".pdf"); } // If you prefer a simpler approach without streams, simply do: //fileId = StorageMock.Store(result.GetContent(), ".pdf"); } catch (ValidationException ex) { // One or more validations failed. We log the error and update the page with a summary of what happened to this document setValidationError(ex.ValidationResults); return; } catch (Exception ex) { // An error has occurred. We log the error and update the page with a summary of what happened to this document setError(ex.Message); return; } // Update the page with a link to the signed file var docItem = DocumentsListView.Items[DocumentIndex]; docItem.DataItem = new DocumentItem() { Id = DocumentIds[DocumentIndex], DownloadLink = "Download.aspx?fileId=" + fileId }; docItem.DataBind(); }
protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { // Get an instance of the Authentication class var auth = Util.GetRestPkiClient().GetAuthentication(); // Call the StartWithWebPki() method, which initiates the authentication. This yields the "token", a 22-character // case-sensitive URL-safe string, which represents this authentication process. We'll use this value to call the // signWithRestPki() method on the Web PKI component (see signature-form.js) and also to call the // CompleteWithWebPki() method on the Click-event handler below (this should not be mistaken with the API access token). var token = auth.StartWithWebPki(Util.GetSecurityContextId()); // We'll need the token later, so we'll put it on ViewState and we'll render a hidden field on the page with it ViewState["Token"] = token; } }
public static string Start(int id) { // Get an instance of the PadesSignatureStarter class, responsible for receiving the signature elements and start the // signature process var signatureStarter = new PadesSignatureStarter(Util.GetRestPkiClient()) { // Set the unit of measurement used to edit the pdf marks and visual representations MeasurementUnits = PadesMeasurementUnits.Centimeters, // Set the signature policy SignaturePolicyId = StandardPadesSignaturePolicies.Basic, // Set the security context to be used to determine trust in the certificate chain SecurityContextId = Util.GetSecurityContextId(), // Set a visual representation for the signature (see function below) VisualRepresentation = getVisualRepresentation(), }; /* * Optionally, add marks to the PDF before signing. These differ from the signature visual representation in that * they are actually changes done to the document prior to signing, not binded to any signature. Therefore, any number * of marks can be added, for instance one per page, whereas there can only be one visual representation per signature. * However, since the marks are in reality changes to the PDF, they can only be added to documents which have no previous * signatures, otherwise such signatures would be made invalid by the changes to the document (see property * PadesSignatureStarter.BypassMarksIfSigned). This problem does not occurr with signature visual representations. * * We have encapsulated this code in a method to include several possibilities depending on the argument passed. * Experiment changing the argument to see different examples of PDF marks. Once you decide which is best for your case, * you can place the code directly here. */ //signatureStarter.PdfMarks.Add(PadesVisualElements.GetPdfMark(1)); // Set the PDF to be signed signatureStarter.SetPdfToSign(Util.GetBatchDocContent(id)); // Call the StartWithWebPki() method, which initiates the signature. This yields the token, a 43-character // case-sensitive URL-safe string, which identifies this signature process. We'll use this value to call the // signWithRestPki() method on the Web PKI component (see batch-signature-optimized-form.js) and also to complete // the signature on the POST action below (this should not be mistaken with the API access token). var token = signatureStarter.StartWithWebPki(); // Send to the javascript the token of the signature process to be used to call Web PKI to perform the signature return(token); }
protected void Page_Load(object sender, EventArgs e) { // Get verification code from query string var formattedVerificationCode = Request.QueryString["code"]; // On PrinterFriendlyVersion.aspx, 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. var verificationCode = AlphaCode.Parse(formattedVerificationCode); // Get document associated with verification code var fileId = StorageMock.LookupVerificationCode(verificationCode); if (fileId == null) { // 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) Thread.Sleep(TimeSpan.FromSeconds(2)); // Return Not Found Response.StatusCode = 404; Response.End(); return; } // Read document from storage var fileContent = StorageMock.Read(fileId); // Open and validate signatures with Rest PKI var client = Util.GetRestPkiClient(); var sigExplorer = new PadesSignatureExplorer(client) { Validate = true, DefaultSignaturePolicyId = StandardPadesSignaturePolicies.Basic, SecurityContextId = Util.GetSecurityContextId(), }; sigExplorer.SetSignatureFile(fileContent); var signature = sigExplorer.Open(); // Set properties for rendering on page (see aspx file) this.FileId = fileId; this.Model = signature; }
protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { // Get an instance of the Authentication class var auth = Util.GetRestPkiClient().GetAuthentication(); // Call the StartWithWebPki() method, which initiates the authentication. This yields the "token", a 22-character // case-sensitive URL-safe string, which represents this authentication process. We'll use this value to call the // signWithRestPki() method on the Web PKI component (see javascript on the view) and also to call the // CompleteWithWebPki() method on the POST action below (this should not be mistaken with the API access token). var token = auth.StartWithWebPki(StandardSecurityContexts.PkiBrazil); // Alternative option: authenticate the user with a custom security context containting, for instance, your private PKI certificate //var token = auth.StartWithWebPki(new Guid("ID OF YOUR CUSTOM SECURITY CONTEXT")); // We'll need the token later, so we'll put it on ViewState and we'll render a hidden field on the page with it ViewState["Token"] = token; } }
private byte[] generatePrinterFriendlyVersion(byte[] pdfContent, string verificationCode) { var client = Util.GetRestPkiClient(); // 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) var formattedVerificationCode = Util.FormatVerificationCode(verificationCode); // Build the verification link from the constant "VerificationLinkFormat" (see above) and the formatted verification code var verificationLink = string.Format(VerificationLinkFormat, formattedVerificationCode); // 1. Upload the PDF var blob = client.UploadFile(pdfContent); // 2. Inspect signatures on the uploaded PDF var sigExplorer = new PadesSignatureExplorer(client) { Validate = true, DefaultSignaturePolicyId = StandardPadesSignaturePolicies.Basic, SecurityContextId = Util.GetSecurityContextId(), }; sigExplorer.SetSignatureFile(blob); var signature = sigExplorer.Open(); // 3. Create PDF with verification information from uploaded PDF var pdfMarker = new PdfMarker(client); pdfMarker.SetFile(blob); // Build string with joined names of signers (see method getDisplayName below) var signerNames = Util.JoinStringsPt(signature.Signers.Select(s => getDisplayName(s.Certificate))); var allPagesMessage = string.Format("Este documento foi assinado digitalmente por {0}.\nPara verificar a validade das assinaturas acesse {1} em {2} e informe o código {3}", signerNames, VerificationSiteNameWithArticle, VerificationSite, formattedVerificationCode); // PdfHelper is a class from the Rest PKI Client "fluent API" that helps to create elements and parameters for the PdfMarker var pdf = new 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) pdfMarker.Marks.Add( pdf.Mark() .OnAllPages() .OnContainer(pdf.Container().Width(1).AnchorRight(1).Height(1).AnchorBottom(1)) .AddElement( pdf.ImageElement() .WithOpacity(75) .WithImage(Util.GetIcpBrasilLogoContent(), "image/png") ) ); // Summary on bottom margin of every page (except on the page which will be created at the end of the document) pdfMarker.Marks.Add( pdf.Mark() .OnAllPages() .OnContainer(pdf.Container().Height(2).AnchorBottom().VarWidth().Margins(1.5, 3.5)) .AddElement( pdf.TextElement() .WithOpacity(75) .AddSection(allPagesMessage) ) ); // 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) pdfMarker.Marks.Add( pdf.Mark() .OnAllPages() .OnContainer(pdf.Container().Width(2).AnchorRight().VarHeight().Margins(1.5, 3.5)) .AddElement( pdf.TextElement() .Rotate90Counterclockwise() .WithOpacity(75) .AddSection(allPagesMessage) ) ); // Create a "manifest" mark on a new page added on the end of the document. We'll add several elements to this mark. var manifestMark = pdf.Mark() .OnNewPage() // This mark's container is the whole page with 1-inch margins .OnContainer(pdf.Container().VarWidthAndHeight().Margins(2.54, 2.54)); // We'll keep track of our "vertical offset" as we add elements to the mark double verticalOffset = 0; double elementHeight; elementHeight = 3; manifestMark // ICP-Brasil logo on the upper-left corner .AddElement( pdf.ImageElement() .OnContainer(pdf.Container().Height(elementHeight).AnchorTop(verticalOffset).Width(elementHeight /* using elementHeight as width because the image is square */).AnchorLeft()) .WithImage(Util.GetIcpBrasilLogoContent(), "image/png") ) // QR Code with the verification link on the upper-right corner .AddElement( pdf.QRCodeElement() .OnContainer(pdf.Container().Height(elementHeight).AnchorTop(verticalOffset).Width(elementHeight /* using elementHeight as width because QR Codes are square */).AnchorRight()) .WithQRCodeData(verificationLink) ) // Header "VERIFICAÇÃO DAS ASSINATURAS" centered between ICP-Brasil logo and QR Code .AddElement( pdf.TextElement() .OnContainer(pdf.Container().Height(elementHeight).AnchorTop(verticalOffset + 0.2).FullWidth()) .AlignTextCenter() .AddSection(pdf.TextSection().WithFontSize(NormalFontSize * 1.6).WithText("VERIFICAÇÃO DAS\nASSINATURAS")) ); verticalOffset += elementHeight; // Vertical padding verticalOffset += 1.7; // Header with verification code elementHeight = 2; manifestMark.AddElement( pdf.TextElement() .OnContainer(pdf.Container().Height(elementHeight).AnchorTop(verticalOffset).FullWidth()) .AlignTextCenter() .AddSection(pdf.TextSection().WithFontSize(NormalFontSize * 1.2).WithText(string.Format("Código para verificação: {0}", formattedVerificationCode))) ); verticalOffset += elementHeight; // Paragraph saying "this document was signed by the following signers etc" and mentioning the time zone of the date/times below elementHeight = 2.5; manifestMark.AddElement( pdf.TextElement() .OnContainer(pdf.Container().Height(elementHeight).AnchorTop(verticalOffset).FullWidth()) .AddSection(pdf.TextSection().WithFontSize(NormalFontSize).WithText(string.Format("Este documento foi assinado digitalmente pelos seguintes signatários nas datas indicadas ({0}):", TimeZoneDisplayName))) ); verticalOffset += elementHeight; // Iterate signers foreach (var signer in signature.Signers) { elementHeight = 1.5; manifestMark // Green "check" or red "X" icon depending on result of validation for this signer .AddElement( pdf.ImageElement() .OnContainer(pdf.Container().Height(0.5).AnchorTop(verticalOffset + 0.2).Width(0.5).AnchorLeft()) .WithImage(Util.GetValidationResultIcon(signer.ValidationResults.IsValid), "image/png") ) // Description of signer (see method getSignerDescription below) .AddElement( pdf.TextElement() .OnContainer(pdf.Container().Height(elementHeight).AnchorTop(verticalOffset).VarWidth().Margins(0.8, 0)) .AddSection(pdf.TextSection().WithFontSize(NormalFontSize).WithText(getSignerDescription(signer))) ); verticalOffset += elementHeight; } // Some vertical padding from last signer verticalOffset += 1; // Paragraph with link to verification site and citing both the verification code above and the verification link below elementHeight = 2.5; manifestMark.AddElement( pdf.TextElement() .OnContainer(pdf.Container().Height(elementHeight).AnchorTop(verticalOffset).FullWidth()) .AddSection(pdf.TextSection().WithFontSize(NormalFontSize).WithText(string.Format("Para verificar a validade das assinaturas, acesse {0} em ", VerificationSiteNameWithArticle))) .AddSection(pdf.TextSection().WithFontSize(NormalFontSize).WithColor(Color.Blue).WithText(VerificationSite)) .AddSection(pdf.TextSection().WithFontSize(NormalFontSize).WithText(" e informe o código acima ou acesse o link abaixo:")) ); verticalOffset += elementHeight; // Verification link elementHeight = 1.5; manifestMark.AddElement( pdf.TextElement() .OnContainer(pdf.Container().Height(elementHeight).AnchorTop(verticalOffset).FullWidth()) .AddSection(pdf.TextSection().WithFontSize(NormalFontSize).WithColor(Color.Blue).WithText(verificationLink)) .AlignTextCenter() ); // Apply marks pdfMarker.Marks.Add(manifestMark); var result = pdfMarker.Apply(); // Return result return(result.GetContent()); }
private void startNextSignature() { // Increment the index of the document currently being signed DocumentIndex += 1; // Check if we have reached the end of the batch, in which case we fill the hidden field "TokenField" with value "(end)", // which signals to the javascript on batch-signature-form.js that the process is completed and the page can be unblocked. if (DocumentIndex == DocumentIds.Count) { TokenField.Value = "(end)"; return; } // Get the ID of the document currently being signed var docId = DocumentIds[DocumentIndex]; string token; try { // Get an instance of the PadesSignatureStarter class, responsible for receiving the signature elements and start the // signature process var signatureStarter = new PadesSignatureStarter(Util.GetRestPkiClient()) { // Set the unit of measurement used to edit the pdf marks and visual representations MeasurementUnits = PadesMeasurementUnits.Centimeters, // Set the signature policy SignaturePolicyId = StandardPadesSignaturePolicies.Basic, // Set the security context to be used to determine trust in the certificate chain SecurityContextId = Util.GetSecurityContextId(), // Set a visual representation for the signature (see function below) VisualRepresentation = getVisualRepresentation(), }; /* * Optionally, add marks to the PDF before signing. These differ from the signature visual representation in that * they are actually changes done to the document prior to signing, not binded to any signature. Therefore, any number * of marks can be added, for instance one per page, whereas there can only be one visual representation per signature. * However, since the marks are in reality changes to the PDF, they can only be added to documents which have no previous * signatures, otherwise such signatures would be made invalid by the changes to the document (see property * PadesSignatureStarter.BypassMarksIfSigned). This problem does not occurr with signature visual representations. * * We have encapsulated this code in a method to include several possibilities depending on the argument passed. * Experiment changing the argument to see different examples of PDF marks. Once you decide which is best for your case, * you can place the code directly here. */ //signatureStarter.PdfMarks.Add(PadesVisualElements.GetPdfMark(1)); // Set the PDF to be signed signatureStarter.SetPdfToSign(Util.GetBatchDocContent(docId)); // Call the StartWithWebPki() method, which initiates the signature. token = signatureStarter.StartWithWebPki(); } catch (ValidationException ex) { // One or more validations failed. We log the error, update the page with a summary of what happened to this document and start the next signature setValidationError(ex.ValidationResults); startNextSignature(); return; } catch (Exception ex) { // An error has occurred. We log the error, update the page with a summary of what happened to this document and start the next signature setError(ex.Message); startNextSignature(); return; } // Send to the javascript the token of the signature process to be used to call Web PKI to perform the signature TokenField.Value = token; }
// This function is called by the Pades Signature Starter action (see PadesSignatureController.cs). // It contains examples of signature visual representation positionings. public static PadesVisualPositioning GetVisualPositioning(int sampleNumber) { switch (sampleNumber) { case 1: // Example #1: automatic positioning on footnote. This will insert the signature, and future signatures, // ordered as a footnote of the last page of the document return(PadesVisualPositioning.GetFootnote(Util.GetRestPkiClient())); case 2: // Example #2: get the footnote positioning preset and customize it var footnotePosition = PadesVisualPositioning.GetFootnote(Util.GetRestPkiClient()); footnotePosition.Container.Left = 2.54; footnotePosition.Container.Bottom = 2.54; footnotePosition.Container.Right = 2.54; return(footnotePosition); case 3: // Example #3: automatic positioning on new page. This will insert the signature, and future signatures, // in a new page appended to the end of the document. return(PadesVisualPositioning.GetNewPage(Util.GetRestPkiClient())); case 4: // Example #4: get the "new page" positioning preset and customize it var newPagePos = PadesVisualPositioning.GetNewPage(Util.GetRestPkiClient()); newPagePos.Container.Left = 2.54; newPagePos.Container.Top = 2.54; newPagePos.Container.Right = 2.54; newPagePos.SignatureRectangleSize.Width = 5; newPagePos.SignatureRectangleSize.Height = 3; return(newPagePos); case 5: // Example #5: manual positioning // The first parameter is the page number. Zero means the signature will be placed on a new page appended to the end of the document return(new PadesVisualManualPositioning(0, new PadesVisualRectangle() { // define a manual position of 5cm x 3cm, positioned at 1 inch from the left and bottom margins Left = 2.54, Bottom = 2.54, Width = 5, Height = 3 })); case 6: // Example #6: custom auto positioning return(new PadesVisualAutoPositioning() { PageNumber = -1, // negative values represent pages counted from the end of the document (-1 is last page) // Specification of the container where the signatures will be placed, one after the other Container = new PadesVisualRectangle() { // Specifying left and right (but no width) results in a variable-width container with the given margins Left = 2.54, Right = 2.54, // Specifying bottom and height (but no top) results in a bottom-aligned fixed-height container Bottom = 2.54, Height = 12.31 }, // Specification of the size of each signature rectangle SignatureRectangleSize = new PadesSize(5, 3), // The signatures will be placed in the container side by side. If there's no room left, the signatures // will "wrap" to the next row. The value below specifies the vertical distance between rows RowSpacing = 1 }); default: return(null); } }
protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { // Get an instance of the PadesSignatureStarter class, responsible for receiving the signature elements and start the // signature process var signatureStarter = Util.GetRestPkiClient().GetPadesSignatureStarter(); // Set the unit of measurement used to edit the pdf marks and visual representations signatureStarter.MeasurementUnits = PadesMeasurementUnits.Centimeters; // Set the file to be signed as a byte array signatureStarter.SetPdfToSign(Util.GetSampleDocContent()); // Set the signature policy signatureStarter.SetSignaturePolicy(StandardPadesSignaturePolicies.Basic); // Set a SecurityContext to be used to determine trust in the certificate chain signatureStarter.SetSecurityContext(StandardSecurityContexts.PkiBrazil); // Note: By changing the SecurityContext above you can accept only certificates from a certain PKI, // for instance, ICP-Brasil (Lacuna.RestPki.Api.StandardSecurityContexts.PkiBrazil). // Set a visual representation for the signature signatureStarter.SetVisualRepresentation(new PadesVisualRepresentation() { // The tags {{signerName}} and {{signerNationalId}} will be substituted according to the user's certificate // signerName -> full name of the signer // signerNationalId -> if the certificate is ICP-Brasil, contains the signer's CPF Text = new PadesVisualText("Signed by {{signerName}} ({{signerNationalId}})") { // Specify that the signing time should also be rendered IncludeSigningTime = true, // Optionally set the horizontal alignment of the text ('Left' or 'Right'), if not set the default is Left HorizontalAlign = PadesTextHorizontalAlign.Left }, // We'll use as background the image in Content/PdfStamp.png Image = new PadesVisualImage(Util.GetPdfStampContent(), "image/png") { // Opacity is an integer from 0 to 100 (0 is completely transparent, 100 is completely opaque). Opacity = 50, // Align the image to the right HorizontalAlign = PadesHorizontalAlign.Right }, // Position of the visual representation. We have encapsulated this code in a method to include several // possibilities depending on the argument passed. Experiment changing the argument to see different examples // of signature positioning. Once you decide which is best for your case, you can place the code directly here. Position = PadesVisualElements.GetVisualPositioning(1) }); /* * Optionally, add marks to the PDF before signing. These differ from the signature visual representation in that * they are actually changes done to the document prior to signing, not binded to any signature. Therefore, any number * of marks can be added, for instance one per page, whereas there can only be one visual representation per signature. * However, since the marks are in reality changes to the PDF, they can only be added to documents which have no previous * signatures, otherwise such signatures would be made invalid by the changes to the document (see property * PadesSignatureStarter.BypassMarksIfSigned). This problem does not occurr with signature visual representations. * * We have encapsulated this code in a method to include several possibilities depending on the argument passed. * Experiment changing the argument to see different examples of PDF marks. Once you decide which is best for your case, * you can place the code directly here. */ //signatureStarter.PdfMarks.Add(PadesVisualElements.GetPdfMark(1)); // Call the StartWithWebPki() method, which initiates the signature. This yields the token, a 43-character // case-sensitive URL-safe string, which identifies this signature process. We'll use this value to call the // signWithRestPki() method on the Web PKI component (see javascript on the view) and also to complete the signature // on the POST action below (this should not be mistaken with the API access token). var token = signatureStarter.StartWithWebPki(); ViewState["Token"] = token; } }