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 async Task <ActionResult> 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. We have // encapsulated the security context choice on Util.cs. SecurityContextId = Util.GetSecurityContextId(), // Set a visual representation for the signature. VisualRepresentation = PadesVisualElements.GetVisualRepresentationForRestPki() }; // Set the document to be signed based on its ID (passed to us from the page). signatureStarter.SetPdfToSign(StorageMock.GetBatchDocPath(id)); /* * 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 // batch-signature-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 = await signatureStarter.StartWithWebPkiAsync(); // Return a JSON with the token obtained from REST PKI. (the page will use jQuery to decode this // value) return(Json(token)); }
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 async Task <string> Start(string userfile) { var storage = new Storage(hostingEnvironment); var client = Util.GetRestPkiClient(restPkiConfig); // Get an instance of the PadesSignatureStarter class, responsible for receiving the signature elements and start the // signature process var signatureStarter = new PadesSignatureStarter(client) { // Set the unit of measurement used to edit the pdf marks and visual representations MeasurementUnits = PadesMeasurementUnits.Centimeters, // Set the signature policy SignaturePolicyId = StandardPadesSignaturePolicies.PkiBrazil.BasicWithPkiBrazilCerts, // Note: Depending on the signature policy chosen above, setting the security context below 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 a SecurityContext to be used to determine trust in the certificate chain //SecurityContextId = new Guid("ID OF YOUR CUSTOM SECURITY CONTEXT"), // For instance, to use the test certificates on Lacuna Test PKI (for development purposes only!): //SecurityContextId = new Guid("803517ad-3bbc-4169-b085-60053a8f6dbf"), // Set a visual representation for the signature VisualRepresentation = new PadesVisualRepresentation() { // The tags {{name}} and {{br_cpf_formatted}} will be substituted according to the user's certificate // // name : full name of the signer // br_cpf_formatted : if the certificate is ICP-Brasil, contains the signer's CPF // // For a full list of the supported tags, see: https://github.com/LacunaSoftware/RestPkiSamples/blob/master/PadesTags.md Text = new PadesVisualText("Signed by {{name}} ({{br_cpf_formatted}})") { // 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(storage.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(client, 1) } }; // Below we'll either set the PDF file to be signed. Prefer passing a path or a stream instead of the file's contents // as a byte array to prevent memory allocation issues with large files. // If the "userfile" URL argument is set, it will contain the filename under the "App_Data" folder. Otherwise // (signature with server file), we'll sign a sample document. if (string.IsNullOrEmpty(userfile)) { signatureStarter.SetPdfToSign(storage.GetSampleDocPath()); } else { Stream userFileStream; if (!storage.TryOpenRead(userfile, out userFileStream)) { throw new Exception("File not found"); } signatureStarter.SetPdfToSign(userFileStream); } /* * 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(storage, 1)); // Call the StartWithWebPkiAsync() 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 angular controller) and also to complete // the signature on the POST action below (this should not be mistaken with the API access token). var token = await signatureStarter.StartWithWebPkiAsync(); return(token); }
public ActionResult Index(string userfile) { // 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 a SecurityContext to be used to determine trust in the certificate chain SecurityContextId = StandardSecurityContexts.PkiBrazil, // Note: By changing the SecurityContext above you can accept certificates from a custom security context created on the Rest PKI website. // Set a visual representation for the signature VisualRepresentation = 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) }, }; // If the user was redirected here by UploadController (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. 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.Replace("_", "."))); // Note: we're passing the filename argument with "." as "_" because of limitations of ASP.NET MVC } /* * 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(); // The token acquired above can only be used for a single signature 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 SetNoCacheHeaders() (in BaseController) which sets HTTP headers to prevent caching of the page. base.SetNoCacheHeaders(); // Render the signature page with the token obtained from REST PKI return(View(new Models.PadesSignatureModel() { Token = token, UserFile = userfile })); }
public async Task <ActionResult> Index(string userfile) { // Verify if the userfile exists and get its absolute path. string userfilePath; if (!StorageMock.TryGetFile(userfile, out userfilePath)) { return(HttpNotFound()); } // 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. We have // encapsulated the security context choice on Util.cs. SecurityContextId = Util.GetSecurityContextId(), // Set a visual representation for the signature. VisualRepresentation = PadesVisualElements.GetVisualRepresentationForRestPki() }; // Set the file to be signed. signatureStarter.SetPdfToSign(userfilePath); /* * 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 // signature-forms.js) and also to complete the signature on the POST action below (this should // not be mistaken with the API access token). var token = await signatureStarter.StartWithWebPkiAsync(); // The token acquired above can only be used for a single signature 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 // SetNoCacheHeaders() (in BaseController) which sets HTTP headers to prevent caching of the // page. base.SetNoCacheHeaders(); // Render the signature page with the token obtained from REST PKI. return(View(new SignatureModel() { Token = token, UserFile = userfile })); }
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 async Task <ActionResult> Index(SignatureStartModel model) { ClientSideSignatureInstructions signatureParams; 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 a SecurityContext to be used to determine trust in the certificate chain. SecurityContextId = Util.GetSecurityContextId(), // Set a visual representation for the signature. VisualRepresentation = new PadesVisualRepresentation() { // The tags {{name}} and {{national_id}} will be substituted according to the user's // certificate: // // name : Full name of the signer; // national_id : If the certificate is ICP-Brasil, contains the signer's CPF. // // For a full list of the supported tags, see: // https://github.com/LacunaSoftware/RestPkiSamples/blob/master/PadesTags.md Text = new PadesVisualText("Signed by {{name}} ({{national_id}})") { // 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) } }; // Set certificate's content. (received from a hidden field on the form submission, its value // is filled on javascript, see signature-start-form.js) signatureStarter.SetSignerCertificate(model.CertContent); // Set PDF to be signed. signatureStarter.SetPdfToSign(Util.GetSampleDocPath()); /* * 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 StartAsync() method, which initiates the signature. This yields the parameters // for the signature using the certificates. signatureParams = await signatureStarter.StartAsync(); } catch (ValidationException ex) { // Return to Index view rendering the error message. ModelState.AddModelError("", ex.Message); return(View()); } // On the next step (Complete action), we'll need once again some information: // - The token that identifies the signature process on REST PKI service. // - The thumbprint of the selected certificate. // - The "to-sign-hash" 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() { Token = signatureParams.Token, CertThumb = model.CertThumb, ToSignHash = signatureParams.ToSignHash, DigestAlgorithmOid = signatureParams.DigestAlgorithmOid }; return(RedirectToAction("Complete")); }
/** * GET /PadesCloudOauthSdk/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. */ public async Task <ActionResult> Complete(string code, string state) { byte[] signatureContent; PKCertificateWithKey signingCertificate; try { // Get an instance of the TrustServiceManager class, responsible for communicating with PSCs // and handling the OAuth flow. var manager = Util.GetTrustServicesManager(); // Complete the authentication process, recovering the session info to be used on the // signature and the custom state (fileId). var completeAuthResult = await manager.CompleteAuthAsync(code, state); // Recover file to be sigend on custom state parameter. var userfile = completeAuthResult.CustomState; // Verify if the userfile exists and get its absolute path. string userfilePath; if (!StorageMock.TryGetFile(userfile, out userfilePath)) { return(HttpNotFound()); } // Get an instance of the PadesSigner class, responsible for receiving the signature elements // and performing the local signature. var signer = new PadesSigner(); // Set signature policy. signer.SetPolicy(GetSignaturePolicy()); // Set file to be signed. signer.SetPdfToSign(userfilePath); // Recover the interface for the cloud certificate to be passed to PadesSigner class. var certificatesWithKey = await completeAuthResult.GetCertificatesWithKeyAsync(); signingCertificate = certificatesWithKey.First(); signer.SetSigningCertificate(signingCertificate); // Set a visual representation for the signature. signer.SetVisualRepresentation(PadesVisualElements.GetVisualRepresentationForPkiSdk(signingCertificate.Certificate)); // Call ComputeSignature(), which does all the work, including validation of the signer's certificate and of the resulting signature signer.ComputeSignature(); // Get the signed PDF as an array of bytes signatureContent = signer.GetPadesSignature(); } 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()); } return(View("SignatureInfo", new SignatureInfoModel() { // Store the signature file on the folder "App_Data/". // With this filename, it can show a link to download the signature file. File = StorageMock.Store(signatureContent, ".pdf"), SignerCertificate = signingCertificate.Certificate })); }
public async Task <ActionResult> Start(BatchSignatureStartRequest request) { // Recover the batch information based on its ID, which contains the user's certificate. var batchInfo = batches[request.BatchId]; // 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 user's certificate. Notice that this step is not necessary on the regular batch // signature example. This enhances the performance of the batch processing. SignerCertificate = Convert.FromBase64String(batchInfo.Certificate), // Set the signature policy. SignaturePolicyId = StandardPadesSignaturePolicies.Basic, // Set a SecurityContext to be used to determine trust in the certificate chain. We have // encapsulated the security context choice on Util.cs. SecurityContextId = Util.GetSecurityContextId(), // Set a visual representation for the signature. VisualRepresentation = new PadesVisualRepresentation() { // The tags {{name}} and {{national_id}} will be substituted according to the user's // certificate: // // name : Full name of the signer; // national_id : If the certificate is ICP-Brasil, contains the signer's CPF. // // For a full list of the supported tags, see: // https://github.com/LacunaSoftware/RestPkiSamples/blob/master/PadesTags.md Text = new PadesVisualText("Signed by {{name}} ({{national_id}})") { // 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) } }; // Set the document to be signed based on its ID. (passed to us from the page) signatureStarter.SetPdfToSign(Util.GetBatchDocPath(request.DocumentId)); // Call the Start() method, which initiates the signature. Notice that, on the regular signature // example, we call the StartWithRestPki() method, which is simpler but with worse performance. // The Start() method will yield not only the token, a 43-character case-sensitive URL-safe // string which identifies this signature process, but also the data that should be used to call // the signHash() function on the Web PKI component (instead of the signWithRestPki() function, // which is also simpler but far slower). var signatureParams = await signatureStarter.StartAsync(); // Notice: it is not necessary to call SetNoCacheHeaders() because this action is a POST action, // therefore no caching of the response will be made by browsers. // Return a JSON with the token obtained from REST PKI, along with the parameters for the // signHash() call. (the page will use jQuery to decode this value) var response = new BatchSignatureStartResponse() { Token = signatureParams.Token, ToSignHash = Convert.ToBase64String(signatureParams.ToSignHash), DigestAlgorithmOid = signatureParams.DigestAlgorithmOid }; return(Json(response)); }
/** * 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. */ public async Task <ActionResult> Authorize(string userfile, string cpf, string service, string password) { byte[] signatureContent; PKCertificateWithKey signingCertificate; try { // Process CPF, removing all formatting. var plainCpf = Regex.Replace(cpf, "/[.-]/", ""); // Get an instance of the TrustServiceManager class, responsible for communicating with PSCs // and handling the OAuth flow. var manager = Util.GetTrustServicesManager(); // 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. var passwordAuthorizeResult = await manager.PasswordAuthorizeAsync(service, plainCpf, password, TrustServiceSessionTypes.SignatureSession); // Verify if the userfile exists and get its absolute path. string userfilePath; if (!StorageMock.TryGetFile(userfile, out userfilePath)) { return(HttpNotFound()); } // Get an instance of the PadesSigner class, responsible for receiving the signature elements // and performing the local signature. var signer = new PadesSigner(); // Set signature policy. signer.SetPolicy(GetSignaturePolicy()); // Set file to be signed. signer.SetPdfToSign(userfilePath); // Recover the interface for the cloud certificate to be passed to PadesSigner class. var certificatesWithKey = await passwordAuthorizeResult.GetCertificatesWithKeyAsync(); signingCertificate = certificatesWithKey.First(); signer.SetSigningCertificate(signingCertificate); // Set a visual representation for the signature. signer.SetVisualRepresentation(PadesVisualElements.GetVisualRepresentationForPkiSdk(signingCertificate.Certificate)); // Call ComputeSignature(), which does all the work, including validation of the signer's certificate and of the resulting signature signer.ComputeSignature(); // Get the signed PDF as an array of bytes signatureContent = signer.GetPadesSignature(); } 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()); } return(View("SignatureInfo", new SignatureInfoModel() { // Store the signature file on the folder "App_Data/". // With this filename, it can show a link to download the signature file. File = StorageMock.Store(signatureContent, ".pdf"), SignerCertificate = signingCertificate.Certificate })); }
public async Task <ActionResult> 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 signature policy. SignaturePolicyId = StandardPadesSignaturePolicies.Basic, // Set a SecurityContext to be used to determine trust in the certificate chain. We have // encapsulated the security context choice on Util.cs. SecurityContextId = Util.GetSecurityContextId(), // Set a visual representation for the signature. VisualRepresentation = new PadesVisualRepresentation() { // The tags {{name}} and {{national_id}} will be substituted according to the user's // certificate: // // name : Full name of the signer; // national_id : If the certificate is ICP-Brasil, contains the signer's CPF. // // For a full list of the supported tags, see: // https://github.com/LacunaSoftware/RestPkiSamples/blob/master/PadesTags.md Text = new PadesVisualText("Signed by {{name}} ({{national_id}})") { // 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) } }; // Set the document to be signed based on its ID. (passed to us from the page) signatureStarter.SetPdfToSign(Util.GetBatchDocPath(id)); /* * 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 StartWithWebPkiAsync() 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 = await signatureStarter.StartWithWebPkiAsync(); // Notice: it is not necessary to call SetNoCacheHeaders() because this action is a POST action, // therefore no caching of the response will be made by browsers. // Return a JSON with the token obtained from REST PKI. (the page will use jQuery to decode this // value) return(Json(token)); }