public ActionResult Index(SignatureStartModel model) { byte[] toSignBytes, transferData; SignatureAlgorithm signatureAlg; try { // Verify if the userfile exists and get its absolute path. string userfilePath; if (!StorageMock.TryGetFile(model.UserFile, out userfilePath)) { return(HttpNotFound()); } // Decode the user's certificate. var cert = PKCertificate.Decode(model.CertContent); // Get an instance of the PadesSigner class. var padesSigner = new PadesSigner(); // Set the file to be signed. padesSigner.SetPdfToSign(userfilePath); // Set the signer certificate. padesSigner.SetSigningCertificate(cert); // Set the signature policy. padesSigner.SetPolicy(GetSignaturePolicy()); // Set a visual representation for the signature. padesSigner.SetVisualRepresentation(PadesVisualElements.GetVisualRepresentationForPkiSdk(cert)); // Generate the "to-sign-bytes". This method also yields the signature algorithm that must // be used on the client-side, based on the signature policy, as well as the "transfer data", // a byte-array that will be needed on the next step. toSignBytes = padesSigner.GetToSignBytes(out signatureAlg, out transferData); } catch (ValidationException ex) { // Some of the operations above may throw a ValidationException, for instance if the certificate // encoding cannot be read or if the certificate is expired. ModelState.AddModelError("", ex.ValidationResults.ToString()); return(View()); } // On the next step (Complete action), we'll need once again some information: // - The thumbprint of the selected certificate. // - The "transfer data" used to validate the signature in complete action. Its content is stored in // a temporary file (with extension .bin) to be shared with the Complete action. // - The "to-sign-hash" (digest of the "to-sign-bytes") to be signed. (see signature-complete-form.js) // - The OID of the digest algorithm to be used during the signature operation. // We'll store these values on TempData, which is a dictionary shared between actions. TempData["SignatureCompleteModel"] = new SignatureCompleteModel() { CertThumb = model.CertThumb, TransferDataFileId = StorageMock.Store(transferData, ".bin"), ToSignHash = signatureAlg.DigestAlgorithm.ComputeHash(toSignBytes), DigestAlgorithmOid = signatureAlg.DigestAlgorithm.Oid }; return(RedirectToAction("Complete", new { userfile = model.UserFile })); }
public IHttpActionResult Start(SignatureStartRequest request) { byte[] toSignBytes, transferData; SignatureAlgorithm signatureAlg; try { // Decode the user's certificate var cert = PKCertificate.Decode(request.Certificate); // Instantiate a PadesSigner class var padesSigner = new PadesSigner(); // Set the PDF to sign, which in the case of this example is a fixed sample document if (!string.IsNullOrEmpty(request.FileId)) { padesSigner.SetPdfToSign(Storage.GetFile(request.FileId)); } else { padesSigner.SetPdfToSign(Storage.GetSampleDocContent()); } // Set the signer certificate padesSigner.SetSigningCertificate(cert); // Set the signature policy padesSigner.SetPolicy(getSignaturePolicy()); // Set the signature's visual representation options (optional) padesSigner.SetVisualRepresentation(getVisualRepresentation(cert)); // Generate the "to-sign-bytes". This method also yields the signature algorithm that must // be used on the client-side, based on the signature policy, as well as the "transfer data", // a byte-array that will be needed on the next step. toSignBytes = padesSigner.GetToSignBytes(out signatureAlg, out transferData); } catch (ValidationException ex) { // Some of the operations above may throw a ValidationException, for instance if the certificate // encoding cannot be read or if the certificate is expired. return(new ResponseMessageResult(Request.CreateResponse(HttpStatusCode.BadRequest, new ValidationErrorModel(ex.ValidationResults)))); } // Create response with some informations that we'll use on Complete action and on client-side. var response = new SignatureStartResponse() { // The "transfer data" for PDF signatures can be as large as the original PDF itself. Therefore, we mustn't use a hidden field // on the page to store it. Here we're using our storage mock (see file Classes\Storage.cs) to simulate storing the transfer data // on a database and saving on a hidden field on the page only the ID that can be used later to retrieve it. Another option would // be to store the transfer data on the Session dictionary. TransferDataFileId = Storage.StoreFile(transferData), // Send to the javascript the "to sign hash" of the document (digest of the "to-sign-bytes") and the digest algorithm that must // be used on the signature algorithm computation ToSignBytes = toSignBytes, DigestAlgorithmOid = signatureAlg.DigestAlgorithm.Oid }; return(Ok(response)); }
protected void SubmitCertificateButton_Click(object sender, EventArgs e) { byte[] toSignBytes, transferData; SignatureAlgorithm signatureAlg; try { // Decode the user's certificate. var cert = PKCertificate.Decode(Convert.FromBase64String(CertificateField.Value)); // Instantiate a PadesSigner class. var padesSigner = new PadesSigner(); // Set the PDF to sign, which in the case of this example is a fixed sample document. padesSigner.SetPdfToSign(Storage.GetSampleDocContent()); // Set the signer certificate. padesSigner.SetSigningCertificate(cert); // Set the signature policy. padesSigner.SetPolicy(getSignaturePolicy()); // Set the signature's visual representation options (optional). padesSigner.SetVisualRepresentation(getVisualRepresentation(cert)); // Generate the "to-sign-bytes". This method also yields the signature algorithm that must // be used on the client-side, based on the signature policy, as well as the "transfer data", // a byte-array that will be needed on the next step. toSignBytes = padesSigner.GetToSignBytes(out signatureAlg, out transferData); } catch (ValidationException ex) { // Some of the operations above may throw a ValidationException, for instance if the certificate // encoding cannot be read or if the certificate is expired. ex.ValidationResults.Errors.ForEach(ve => ModelState.AddModelError("", ve.ToString())); return; } // The "transfer data" for PDF signatures can be as large as the original PDF itself. Therefore, we // mustn't use a hidden field on the page to store it. Here we're using our storage mock // (see file Classes\Storage.cs) to simulate storing the transfer data on a database and saving on a // hidden field on the page only the ID that can be used later to retrieve it. Another option would // be to store the transfer data on the Session dictionary. TransferDataFileIdField.Value = Storage.StoreFile(transferData); // Send to the javascript the "to sign hash" of the document (digest of the "to-sign-bytes") and the // digest algorithm that must be used on the signature algorithm computation. ToSignHashField.Value = Convert.ToBase64String(signatureAlg.DigestAlgorithm.ComputeHash(toSignBytes)); DigestAlgorithmField.Value = signatureAlg.DigestAlgorithm.Oid; }
public ActionResult Start(BatchSignatureStartRequest request) { byte[] toSignBytes, transferData; SignatureAlgorithm signatureAlg; try { // Decode the user's certificate var cert = PKCertificate.Decode(request.CertContent); // Instantiate a PadesSigner class var padesSigner = new PadesSigner(); // Set the PDF to sign, which in the case of this example is one of the batch documents padesSigner.SetPdfToSign(StorageMock.GetBatchDocPath(request.Id)); // Set the signer certificate padesSigner.SetSigningCertificate(cert); // Set the signature policy. padesSigner.SetPolicy(GetSignaturePolicy()); // Set a visual representation for the signature. padesSigner.SetVisualRepresentation(PadesVisualElements.GetVisualRepresentationForPkiSdk(cert)); // Generate the "to-sign-bytes". This method also yields the signature algorithm that must // be used on the client-side, based on the signature policy, as well as the "transfer data", // a byte-array that will be needed on the next step. toSignBytes = padesSigner.GetToSignBytes(out signatureAlg, out transferData); } catch (ValidationException ex) { // Some of the operations above may throw a ValidationException, for instance if the certificate // encoding cannot be read or if the certificate is expired. return(new HttpStatusCodeResult(500, ex.ValidationResults.ToString())); } // For the next steps, we'll need once again some information: // - The "transfer data" filename. Its content is stored in a temporary file (with extension .bin) to // be shared with the Complete action. // - The "to-sign-hash" (digest of the "to-sign-bytes"). And the OID of the digest algorithm to be // used during the signature operation. this information is need in the signature computation with // Web PKI component. (see batch-signature-form.js) return(Json(new BatchSignatureStartResponse() { TransferDataFileId = StorageMock.Store(transferData, ".bin"), ToSignHash = signatureAlg.DigestAlgorithm.ComputeHash(toSignBytes), DigestAlgorithmOid = signatureAlg.DigestAlgorithm.Oid })); }
public ActionResult Start(SignatureStartModel model) { byte[] toSignBytes, transferData; SignatureAlgorithm signatureAlg; try { // Verify if the userfile exists and get its absolute path. string userfilePath; if (!StorageMock.TryGetFile(model.UserFile, out userfilePath)) { return(HttpNotFound()); } // Decode the user's certificate. var cert = PKCertificate.Decode(model.CertContent); // Get an instance of the PadesSigner class. var padesSigner = new PadesSigner(); // Set the file to be signed. padesSigner.SetPdfToSign(userfilePath); // REQUIRED! // Provide the signer's certificate. You must sign with a valid digital // certificate of a doctor, who was registered on CRM. In this sample, // we used a sample certificate stored on server to do the execute this // sample. padesSigner.SetSigningCertificate(cert); // REQUIRED! // Define the trust arbitrator, which will configure the signer to // some kind of certificate. In the case of this sample, only // ICP-Brasil certificates will be accepted in the defined standard. var trustArbitrator = new LinkedTrustArbitrator(TrustArbitrators.PkiBrazil); #if DEBUG // For development purposes, we also trust in Lacuna Software's test certificates. var lacunaRoot = Lacuna.Pki.PKCertificate.Decode(Convert.FromBase64String("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")); trustArbitrator.Add(new TrustedRoots(lacunaRoot)); #endif // REQUIRED! // Use a policy accepted by ICP-Brasil. We use the trust arbitrator // defined above to configure the policy. padesSigner.SetPolicy(PadesPoliciesForGeneration.GetPadesBasic(trustArbitrator)); // REQUIRED! // Use a custom signature field name. This field MUST have the // "Emitente" keyword as the last keyword. padesSigner.SetCustomSignatureFieldName("Signature1 Emitente"); // REQUIRED! // Set Certification Level to not allow changes after signed. padesSigner.SetCertificationLevel(PadesCertificationLevel.CertifiedNoChangesAllowed); // Set a visual representation for the signature. padesSigner.SetVisualRepresentation(PadesVisualElements.GetVisualRepresentationForPkiSdk(cert)); // Generate the "to-sign-bytes". This method also yields the signature algorithm that must // be used on the client-side, based on the signature policy, as well as the "transfer data", // a byte-array that will be needed on the next step. toSignBytes = padesSigner.GetToSignBytes(out signatureAlg, out transferData); } catch (ValidationException ex) { // Some of the operations above may throw a ValidationException, for instance if the certificate // encoding cannot be read or if the certificate is expired. ModelState.AddModelError("", ex.ValidationResults.ToString()); return(View()); } // On the next step (Complete action), we'll need once again some information: // - The thumbprint of the selected certificate. // - The "transfer data" used to validate the signature in complete action. Its content is stored in // a temporary file (with extension .bin) to be shared with the Complete action. // - The "to-sign-hash" (digest of the "to-sign-bytes") to be signed. (see signature-complete-form.js) // - The OID of the digest algorithm to be used during the signature operation. // We'll store these values on TempData, which is a dictionary shared between actions. TempData["SignatureCompleteModel"] = new SignatureCompleteModel() { CertThumb = model.CertThumb, TransferDataFileId = StorageMock.Store(transferData, ".bin"), ToSignHash = signatureAlg.DigestAlgorithm.ComputeHash(toSignBytes), DigestAlgorithmOid = signatureAlg.DigestAlgorithm.Oid }; return(RedirectToAction("Complete", new { userfile = model.UserFile })); }
public IHttpActionResult Start(BatchSignatureStartRequest request) { byte[] toSignBytes, transferData; SignatureAlgorithm signatureAlg; try { // Decode the user's certificate var cert = PKCertificate.Decode(request.CertContent); // Instantiate a PadesSigner class var padesSigner = new PadesSigner(); // Set the PDF to sign, which in the case of this example is one of the batch documents padesSigner.SetPdfToSign(Storage.GetBatchDocContent(request.Id)); // Set the signer certificate padesSigner.SetSigningCertificate(cert); // Set the signature policy padesSigner.SetPolicy(getSignaturePolicy()); // Set the signature's visual representation options (this is optional). For more information, see // http://pki.lacunasoftware.com/Help/html/98095ec7-2742-4d1f-9709-681c684eb13b.htm var visual = new PadesVisualRepresentation2() { // Text of the visual representation Text = new PadesVisualText() { // Compose the message CustomText = $"Assinado digitalmente por {cert.SubjectDisplayName}", // 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 }, // Background image of the visual representation Image = new PadesVisualImage() { // We'll use as background the image in Content/PdfStamp.png Content = Storage.GetPdfStampContent(), // 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 }, // Set the position of the visual representation Position = PadesVisualAutoPositioning.GetFootnote() }; padesSigner.SetVisualRepresentation(visual); // Generate the "to-sign-bytes". This method also yields the signature algorithm that must // be used on the client-side, based on the signature policy, as well as the "transfer data", // a byte-array that will be needed on the next step. toSignBytes = padesSigner.GetToSignBytes(out signatureAlg, out transferData); } catch (ValidationException ex) { // Some of the operations above may throw a ValidationException, for instance if the certificate // encoding cannot be read or if the certificate is expired. var message = Request.CreateErrorResponse(HttpStatusCode.InternalServerError, ex.ValidationResults.ToString()); return(ResponseMessage(message)); } // For the next steps, we'll need once again some information: // - The "transfer data" filename. Its content is stored in a temporary file (with extension .bin) to // be shared with the Complete action. // - The "to-sign-hash" (digest of the "to-sign-bytes"). And the OID of the digest algorithm to be // used during the signature operation. this information is need in the signature computation with // Web PKI component. (see batch-signature-form.js) return(Ok(new BatchSignatureStartResponse() { TransferDataFileId = Storage.StoreFile(transferData, ".bin"), ToSignHash = signatureAlg.DigestAlgorithm.ComputeHash(toSignBytes), DigestAlgorithmOid = signatureAlg.DigestAlgorithm.Oid })); }
public ActionResult Index(SignatureStartModel model) { byte[] toSignBytes, transferData; SignatureAlgorithm signatureAlg; try { // Decode the user's certificate var cert = PKCertificate.Decode(model.CertContent); // Instantiate a PadesSigner class var padesSigner = new PadesSigner(); // Set the PDF to sign, which in the case of this example is a fixed sample document padesSigner.SetPdfToSign(Storage.GetSampleDocContent()); // Set the signer certificate padesSigner.SetSigningCertificate(cert); // Set the signature policy padesSigner.SetPolicy(getSignaturePolicy()); // Set the signature's visual representation options (this is optional). For more information, see // http://pki.lacunasoftware.com/Help/html/98095ec7-2742-4d1f-9709-681c684eb13b.htm var visual = new PadesVisualRepresentation2() { // Text of the visual representation Text = new PadesVisualText() { // Compose the message CustomText = String.Format("Assinado digitalmente por {0}", cert.SubjectDisplayName), // 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 }, // Background image of the visual representation Image = new PadesVisualImage() { // We'll use as background the image in Content/PdfStamp.png Content = Storage.GetPdfStampContent(), // 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 }, // Set the position of the visual representation Position = PadesVisualAutoPositioning.GetFootnote() }; padesSigner.SetVisualRepresentation(visual); // Generate the "to-sign-bytes". This method also yields the signature algorithm that must // be used on the client-side, based on the signature policy, as well as the "transfer data", // a byte-array that will be needed on the next step. toSignBytes = padesSigner.GetToSignBytes(out signatureAlg, out transferData); } catch (ValidationException ex) { // Some of the operations above may throw a ValidationException, for instance if the certificate // encoding cannot be read or if the certificate is expired. ModelState.AddModelError("", ex.ValidationResults.ToString()); return(View()); } // On the next step (Complete action), we'll need once again some information: // - The content of the selected certificate only used to render the user's certificate information // after the signature is completed. It is no longer needed for the signature process. // - The thumbprint of the selected certificate. // - The "transfer data" used to validate the signature in complete action. // - The "to-sign-hash" (digest of the "to-sign-bytes") to be signed. (see signature-complete-form.js) // - The OID of the digest algorithm to be used during the signature operation. // We'll store these values on TempData, which is a dictionary shared between actions. TempData["SignatureCompleteModel"] = new SignatureCompleteModel() { CertContent = model.CertContent, CertThumb = model.CertThumb, TransferData = transferData, ToSignHash = signatureAlg.DigestAlgorithm.ComputeHash(toSignBytes), DigestAlgorithmOid = signatureAlg.DigestAlgorithm.Oid }; return(RedirectToAction("Complete")); }
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 // "ToSignHashField" 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) { ToSignHashField.Value = "(end)"; return; } // Get the ID of the document currently being signed. var docId = DocumentIds[DocumentIndex]; byte[] toSignBytes, transferData; SignatureAlgorithm signatureAlg; try { // Decode the user's certificate. var cert = PKCertificate.Decode(Convert.FromBase64String(CertificateField.Value)); // Instantiate a PadesSigner class. var padesSigner = new PadesSigner(); // Set the PDF to sign. padesSigner.SetPdfToSign(Storage.GetBatchDocContent(docId)); // Set the signer certificate. padesSigner.SetSigningCertificate(cert); // Set the signature policy. padesSigner.SetPolicy(getSignaturePolicy()); // Set the signature's visual representation options (optional). padesSigner.SetVisualRepresentation(getVisualRepresentation(cert)); // Generate the "to-sign-bytes". This method also yields the signature algorithm that must // be used on the client-side, based on the signature policy, as well as the "transfer data", // a byte-array that will be needed on the next step. toSignBytes = padesSigner.GetToSignBytes(out signatureAlg, out transferData); } 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. logger.Error(ex, "Validation error starting the signature of a batch document"); 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. logger.Error(ex, "Error starting the signature of a batch document"); setError(ex.Message); startNextSignature(); return; } // The "transfer data" for PDF signatures can be as large as the original PDF itself. Therefore, we // mustn't use a hidden field on the page to store it. Here we're using our storage mock // (see file Classes\Storage.cs) to simulate storing the transfer data on a database and saving on a // hidden field on the page only the ID that can be used later to retrieve it. Another option would // be to store the transfer data on the Session dictionary. TransferDataFileIdField.Value = Storage.StoreFile(transferData); // Send to the javascript the "to sign hash" of the document (digest of the "to-sign-bytes") and the // digest algorithm that must be used on the signature algorithm computation ToSignHashField.Value = Convert.ToBase64String(signatureAlg.DigestAlgorithm.ComputeHash(toSignBytes)); DigestAlgorithmField.Value = signatureAlg.DigestAlgorithm.Oid; }