private static bool SignFile(string file, PKCertificateWithKey certWithKey, PadesPolicySpec policy, PadesVisualRepresentation2 visual, Metadata metadata, string outputDir, string outputName = null) { var documentoToSign = File.ReadAllBytes(file); if (metadata != null) { using (var buffer = new MemoryStream()) { using (var stream = new MemoryStream(documentoToSign)) { DoConvertToPdfA(stream, metadata, buffer); } documentoToSign = buffer.ToArray(); } } var signer = new PadesSigner(); signer.SetSigningCertificate(certWithKey); signer.SetPdfToSign(documentoToSign); signer.SetPolicy(policy); signer.SetVisualRepresentation(visual); signer.SetCertificateValidationConfigurator(ConfigureNoValidation); if (string.IsNullOrWhiteSpace(outputName)) { outputName = Path.GetFileName(file); } try { signer.ComputeSignature(); var signed = signer.GetPadesSignature(); File.WriteAllBytes(Path.Combine(outputDir, outputName), signed); } catch (Exception exception) { Log(exception.ToString(), file); return(false); } return(true); }
private async void signButtonClick(object sender, RoutedEventArgs e) { //var progressDialog = await this.ShowProgressAsync("Please wait...", "Signing"); Pkcs11CertificateStore p11Store = null; addLog($"Signature process begin"); progressBar.Value = 10; try { var signatureStarter = new PadesSignatureStarter(restPkiClient) { // 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 = Guid.Parse("803517ad-3bbc-4169-b085-60053a8f6dbf"), //SecurityContextId =StandardSecurityContexts.PkiBrazil, // Note: this SecurityContext above accept unsecured certificates. You can create custom security context on the Rest PKI website. // Set a visual representation for the signature VisualRepresentation = createVisualRepresentation() }; progressBar.Value = 15; // 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(FileToSign)) { // Set the PDF to be signed as a byte array signatureStarter.SetPdfToSign(Signer.Resources.SampleDocument); } else { // Set the path of the file to be signed addLog($"file size {(new FileInfo(FileToSign).Length / 1024.0).ToString("0.00")} KBytes"); signatureStarter.SetPdfToSign(FileToSign); } /* * 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). // Find selected certificate with key // -------------------------------------------------------------- PKCertificateWithKey certWithKey = null; var selectedThumbprint = (CertificatesCB.SelectedItem as ComboCertificate).Certificate.ThumbprintSHA256; p11Store = Pkcs11CertificateStore.Load(getPkcs11Modules(), new P11LoginProvider()); // search on pkcs11 store if (findCertificate(p11Store.GetCertificatesWithKey(), selectedThumbprint, out certWithKey)) { } else if (findCertificate(WindowsCertificateStore.LoadPersonalCurrentUser().GetCertificatesWithKey(), selectedThumbprint, out certWithKey)) { } else { throw new Exception("Selected certificate not found"); } // -------------------------------------------------------------- signatureStarter.SetSignerCertificate(certWithKey.Certificate.EncodedValue); progressBar.Value = 30; addLog($"Step 1: Start Signature"); var sw = Stopwatch.StartNew(); Token = await signatureStarter.StartAsync(); sw.Stop(); addLog($"Step 1: Signature Started, elapsed {sw.Elapsed.TotalSeconds:N1}s"); progressBar.Value = 50; addLog($"Signing with {certWithKey.Certificate.SubjectDisplayName}"); var signature = certWithKey.SignData(Lacuna.Pki.DigestAlgorithm.GetInstanceByOid(Token.DigestAlgorithmOid), Token.ToSignData); addLog($"Signed"); progressBar.Value = 70; var signatureFinisher = new PadesSignatureFinisher2(restPkiClient) { Token = Token.Token, Signature = signature }; sw = Stopwatch.StartNew(); // Call the Finish() method, which finalizes the signature process and returns a SignatureResult object addLog($"Step 2: Finish Signature"); var signatureResult = await signatureFinisher.FinishAsync(); sw.Stop(); addLog($"Step 2: Signature Finished, elapsed {sw.Elapsed.TotalSeconds:N1}s"); SignedFile = System.IO.Path.Combine(Path.GetDirectoryName(FileToSign), Path.GetFileNameWithoutExtension(FileToSign) + "-signed" + Path.GetExtension(FileToSign)); signatureResult.WriteToFile(SignedFile); //BusyIndicator.IsBusy = false; progressBar.Value = 100; OpenFileSignedBt.IsEnabled = true; addLog($"File signed: {SignedFile}"); } catch (Exception ex) { addLog(ex.ToString()); } finally { if (p11Store != null) { p11Store.Dispose(); } } progressBar.Value = 0; }
private bool findCertificate(List <PKCertificateWithKey> certificates, byte[] thumbprint, out PKCertificateWithKey cert) { cert = certificates.FirstOrDefault(c => c.Certificate.ThumbprintSHA256.SequenceEqual(thumbprint)); return(cert != null); }
public CertificateItem(PKCertificateWithKey cert) { this.CertificateWithKey = cert; }
static void Sign(PKCertificateWithKey certWithKey, string inputDir, string outputDir, bool reprocess, string visualRep, Metadata metadata) { var sw = Stopwatch.StartNew(); Console.WriteLine("Listing files to be signed."); var files = Directory.EnumerateFiles(inputDir, "*.pdf").ToList(); if (reprocess) { Console.WriteLine("Preparing to reprocess not signed files"); var signerFiles = Directory.EnumerateFiles(outputDir, "*.pdf").ToList(); files = files.Except(signerFiles).ToList(); } Console.WriteLine($"{files.Count().ToString("N0")} files to be signed in directory {outputDir}"); Console.WriteLine("Started signing process"); //Console.WriteLine($"----------------------------------------------------------".Pastel(Color.ForestGreen)); var errorFiles = new ConcurrentBag <string>(); try { var visual = CreateVisualRepresentation(certWithKey.Certificate, visualRep, (metadata != null)); var policy = GetSignaturePolicy().GetPolicy(certWithKey.Certificate); policy.SignerSpecs.AttributeGeneration.EnableLtv = false; // -------------- Parallel.ForEach(files, new ParallelOptions() { MaxDegreeOfParallelism = 2 }, (file) => { if (!SignFile(file, certWithKey, policy, visual, metadata, outputDir)) { errorFiles.Add(file); var e = Interlocked.Increment(ref fileErrors); Console.SetCursorPosition(0, Console.CursorTop); Console.Write($"Files to be reprocessed {e.ToString("N0")}"); LogAssinados(file, false); return; } else { LogAssinados(file, true); } var y = Interlocked.Increment(ref filesSigned); if (y % 100 == 0) { Console.SetCursorPosition(0, Console.CursorTop); Console.Write($"Files {y.ToString("N0")} signed in {sw.Elapsed.TotalSeconds.ToString("N1")}s ({(y / sw.Elapsed.TotalSeconds).ToString("N1")} signatures/s)"); } }); Console.WriteLine(); Console.WriteLine($"Reprocessing {errorFiles.Count:N0} files"); foreach (var errorFile in errorFiles) { SignFile(errorFile, certWithKey, policy, visual, metadata, outputDir); } } catch (Exception ex) { Log(ex.ToString()); Console.WriteLine($"Error: {ex}"); } Console.WriteLine(); Console.WriteLine($"Finish signing process"); Console.WriteLine(); Console.WriteLine($"----------------------------------------------------"); Console.WriteLine($"Files:{files.Count():N0} {sw.Elapsed.TotalSeconds:N1}s ({files.Count() / sw.Elapsed.TotalSeconds:N1}) signatures/s"); Console.ReadLine(); }
static void process(Options options) { PkiConfig.LoadLicense(Convert.FromBase64String(LicenseBase64)); var isTest = options.Test > 0; var testCount = options.Test; var documentsInputDir = options.SourceDir; var signedDocumentsOutputDir = options.DestinationDir; if (isTest) { Util.CheckTestDirectories(documentsInputDir, signedDocumentsOutputDir); DeleteFiles(documentsInputDir, signedDocumentsOutputDir); PdfGenerate(testCount, documentsInputDir); } else { if (!Directory.Exists(documentsInputDir) && string.IsNullOrWhiteSpace(options.File)) { Console.WriteLine($"Error! The directory was not found: {documentsInputDir}"); return; } if (!Directory.Exists(signedDocumentsOutputDir) && string.IsNullOrWhiteSpace(options.File)) { Directory.CreateDirectory(signedDocumentsOutputDir); } Console.WriteLine(); } // Signer certificate PKCertificateWithKey cert = null; var store = Pkcs11CertificateStore.Load("eTPKCS11.dll", new StaticLoginProvider(options.Pin)); if (string.IsNullOrEmpty(options.CertThumbprint)) { List <PKCertificateWithKey> certificates; Console.WriteLine(); Console.WriteLine("Listing Certificates..."); if (string.IsNullOrEmpty(options.Pin)) { certificates = WindowsCertificateStore.LoadPersonalCurrentUser().GetCertificatesWithKey(); } else { certificates = store.GetCertificatesWithKey(); } for (var i = 0; i < certificates.Count; i++) { Console.WriteLine($"[{i}] {certificates[i].Certificate.SubjectDisplayName} (Issued by {certificates[i].Certificate.IssuerDisplayName})"); } Console.WriteLine(); Console.Write("Select the signer certificate: "); var indexstring = Console.ReadLine(); if (!int.TryParse(indexstring, out var index)) { Console.WriteLine($"Error! Invalid index: {indexstring}"); return; } cert = certificates[index]; } else { var thumbprint = PkiUtil.DecodeHexString(options.CertThumbprint); if (string.IsNullOrEmpty(options.Pin)) { cert = WindowsCertificateStore.LoadPersonalCurrentUser().GetCertificatesWithKey().FirstOrDefault(c => c.Certificate.ThumbprintSHA1.SequenceEqual(thumbprint)); } else { cert = store.GetCertificatesWithKey().FirstOrDefault(c => c.Certificate.ThumbprintSHA1.SequenceEqual(thumbprint)); } if (cert == null) { Console.WriteLine($"Error! No certificate was found with thumbprint: {options.CertThumbprint}"); return; } } Console.WriteLine($"Signer: {cert.Certificate.SubjectDisplayName} (thumbprint: {Util.ToHex(cert.Certificate.ThumbprintSHA1)})"); Metadata metadata = null; if (!string.IsNullOrEmpty(options.Metadata) && Util.FileExists(options.Metadata)) { try { var metadataContent = File.ReadAllBytes(options.Metadata); var metadataJson = Encoding.UTF8.GetString(metadataContent); metadata = JsonConvert.DeserializeObject <MetadataModel>(metadataJson).ToEntity(); } catch (Exception ex) { Log(ex.ToString()); Console.WriteLine($"Error parsing metadata file: {ex}"); } } if (string.IsNullOrWhiteSpace(options.File)) { Console.WriteLine("Getting things ready."); Sign(cert, documentsInputDir, signedDocumentsOutputDir, options.Reprocess, options.VisualRep, metadata); } else { var visual = CreateVisualRepresentation(cert.Certificate, options.VisualRep, (metadata != null)); var policy = GetSignaturePolicy().GetPolicy(cert.Certificate); policy.SignerSpecs.AttributeGeneration.EnableLtv = false; if (!SignFile(options.File, cert, policy, visual, metadata, "", "Signed_" + options.File)) { Console.WriteLine($"Error signing file"); return; } else { Console.WriteLine($"File successfully signed."); } } store.Dispose(); }