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); // Set the security context to be used to determine trust in the certificate chain signatureStarter.SetSecurityContext(Util.GetSecurityContextId()); // 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); // Set the security context to be used to determine trust in the certificate chain signatureStarter.SetSecurityContext(Util.GetSecurityContextId()); // Optionally, set whether the content should be encapsulated in the resulting CMS. If this parameter is ommitted, // the following rules apply: // - If no CmsToCoSign 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)); } 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)); } 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 Click-event handler 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 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; }
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; }
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()); }