EasySign BETA
Digital Signing Tool
Loading...
Searching...
No Matches
BundleWorker.cs
Go to the documentation of this file.
1using System.Security.Cryptography.X509Certificates;
2
3using Microsoft.Extensions.Logging;
4
5using Spectre.Console;
6
8{
9 public abstract partial class CommandProvider<TBundle, TConfiguration>
10 {
14 public TBundle? Bundle { get; protected set; }
15
20 protected abstract void InitializeBundle(string bundlePath);
21
28 protected bool LoadBundle(bool readOnly = true)
29 {
30 if (Bundle == null)
31 {
32 throw new ApplicationException("Bundle is not initialized");
33 }
34
35 try
36 {
37 Bundle.LoadFromFile(readOnly);
38
39 if (!string.IsNullOrEmpty(Bundle.Manifest.UpdatedBy) && Bundle.Manifest.UpdatedBy != Bundle.GetType().FullName)
40 {
41 Logger.LogWarning("Bundle was created by a different application");
42 AnsiConsole.MarkupLine($"[{Color.Orange1}]Warning:[/] Bundle was created by a different application");
43 }
44
45 return true;
46 }
47 catch (FileNotFoundException fnfex)
48 {
49 Logger.LogError(fnfex, "Bundle file not found: {BundlePath}", Bundle.BundlePath);
50 AnsiConsole.MarkupLine($"[red]File not found: {Bundle.BundlePath}[/]");
51 }
52 catch (Exception ex)
53 {
54 Logger.LogError(ex, "Failed to load bundle from file: {BundlePath}", Bundle.BundlePath);
55 AnsiConsole.MarkupLine($"[{Color.Red}]Failed to load file: {Bundle.BundlePath}[/]");
56 AnsiConsole.MarkupLine($"[{Color.Red}]Error:[/] {ex.GetType().Name}: {ex.Message}");
57 }
58
59 return false;
60 }
61
83 protected virtual void RunAdd(StatusContext statusContext, string[] files, bool replace, bool recursive, bool continueOnError, bool force)
84 {
85 Logger.LogInformation("Running add command");
86
87 if (Bundle == null)
88 {
89 throw new ApplicationException("Bundle is not initialized");
90 }
91
92 if (!Bundle.Loaded && File.Exists(Bundle.BundlePath))
93 {
94 Logger.LogDebug("A bundle file exists, loading bundle");
95 statusContext.Status("[yellow]Loading Bundle[/]");
96
97 if (!LoadBundle(false)) return;
98
99 if (!force && Bundle.Signatures.Entries.Count > 0)
100 {
101 Logger.LogError("Bundle is already signed, cannot add files");
102 AnsiConsole.MarkupLine($"[{Color.Red}]Cannot add files to a signed bundle[/]");
103 return;
104 }
105 }
106
107 statusContext.Status("[yellow]Adding Files[/]");
108
109 if (files.Length == 0)
110 {
111 Logger.LogDebug("Discovering files in the directory: {RootPath}", Bundle.RootPath);
112
113 if ((files = Utilities.SafeEnumerateFiles(Bundle.RootPath, "*", recursive).ToArray()).Length == 0)
114 {
115 Logger.LogWarning("No files found in the directory: {RootPath}", Bundle.RootPath);
116 AnsiConsole.MarkupLine($"[{Color.Red}]No files found in the directory: {Bundle.RootPath}[/]");
117 return;
118 }
119 else
120 {
121 Logger.LogInformation("Discovered {FileCount} files in the directory: {RootPath}", files.Length, Bundle.RootPath);
122 AnsiConsole.MarkupLine($"[{Color.Green}]Discovered {files.Length} files in the directory: {Bundle.RootPath}[/]");
123 }
124 }
125
126 Logger.LogInformation("Starting file adder multi-thread task");
127 bool errorOccurred = false;
128 bool bundleUpdated = false;
129
130 _ = Parallel.ForEach(files, (file, state) =>
131 {
132 if (file == Bundle.BundlePath)
133 {
134 Logger.LogWarning("File {file} is the bundle file itself", file);
135 AnsiConsole.MarkupLine($"[{Color.Yellow}]Ignored:[/] File {file} is the bundle file itself");
136 return;
137 }
138
139 string entryName = Manifest.GetNormalizedEntryName(Path.GetRelativePath(Bundle.RootPath, file));
140
141 Logger.LogInformation("Processing file: {EntryName}", entryName);
142
143 try
144 {
145 if (!Utilities.IsFileWithinRoot(file, Bundle.RootPath))
146 {
147 Logger.LogWarning("File {file} is outside the bundle root path", file);
148 AnsiConsole.MarkupLine($"[{Color.Yellow}]Ignored:[/] File {file} is outside the bundle root path");
149 return;
150 }
151
152 if (Bundle.Manifest.Entries.ContainsKey(entryName))
153 {
154 if (!replace)
155 {
156 Logger.LogWarning("Entry already exists: {EntryName}", entryName);
157 AnsiConsole.MarkupLine($"[{Color.Yellow}]Exists:[/] {entryName}");
158 return;
159 }
160
161 Logger.LogDebug("Replacing entry: {EntryName}", entryName);
162
163 Bundle.DeleteEntry(entryName);
164 Bundle.AddEntry(file);
165 bundleUpdated = true;
166
167 Logger.LogInformation("Entry: {EntryName} Replaced", entryName);
168 AnsiConsole.MarkupLine($"[{Color.Cyan2}]Replaced:[/] {entryName}");
169 }
170 else
171 {
172 Logger.LogDebug("Adding entry: {EntryName}", entryName);
173
174 Bundle.AddEntry(file);
175 bundleUpdated = true;
176
177 Logger.LogInformation("Entry: {EntryName} Added", entryName);
178 AnsiConsole.MarkupLine($"[blue]Added:[/] {entryName}");
179 }
180 }
181 catch (Exception ex)
182 {
183 errorOccurred = true;
184
185 Logger.LogError(ex, "Error occurred while adding entry: {EntryName}", entryName);
186 AnsiConsole.MarkupLine($"[{Color.Red}]Error:[/] {entryName} ({ex.GetType().Name}: {ex.Message})");
187
188 if (!continueOnError)
189 {
190 Logger.LogWarning("Stopping add operation due to error");
191 state.Stop();
192 }
193 }
194 });
195
196 AnsiConsole.WriteLine();
197
198 if (errorOccurred)
199 {
200 AnsiConsole.MarkupLine("[orange]One or more errors occurred, check the console output or logs for more information[/]");
201 }
202
203 if (bundleUpdated && (continueOnError || !errorOccurred))
204 {
205 Logger.LogInformation("Saving bundle");
206 statusContext.Status("[yellow]Saving Bundle[/]");
207
208 Bundle.Update();
209
210 Logger.LogInformation("Bundle saved successfully");
211 AnsiConsole.MarkupLine($"[green]File: {Bundle.BundlePath} Saved successfully[/]");
212 }
213 else
214 {
215 Logger.LogInformation("No changes were made to the bundle");
216 AnsiConsole.MarkupLine("[yellow]No changes were made to the file[/]");
217 }
218 }
219
226 protected virtual void RunInfo(StatusContext statusContext)
227 {
228 Logger.LogInformation("Running info command");
229
230 if (Bundle == null)
231 {
232 throw new ApplicationException("Bundle is not initialized");
233 }
234
235 Logger.LogDebug("Loading bundle");
236 statusContext.Status("[yellow]Loading Bundle[/]");
237 if (!LoadBundle()) return;
238
239 Grid bundleGrid = new Grid();
240 bundleGrid.AddColumn(new GridColumn().NoWrap());
241 bundleGrid.AddColumn(new GridColumn().PadLeft(2));
242
243 bundleGrid.AddRow("Bundle Info:");
244 bundleGrid.AddRow(" Full Path:", Bundle.BundlePath);
245 bundleGrid.AddRow(" Updated By:", Bundle.Manifest.UpdatedBy ?? "N/A");
246 bundleGrid.AddRow(" Protected Entry Names:", Bundle.Manifest.ProtectedEntryNames.Count.ToString());
247 bundleGrid.AddRow(" Store Files In Bundle:", Bundle.Manifest.StoreOriginalFiles ? "Yes" : "No");
248 bundleGrid.AddRow(" Manifest Entries:", Bundle.Manifest.Entries.Count.ToString());
249 bundleGrid.AddRow(" Manifest Is Signed:", Bundle.Signatures.Entries.Count > 0 ? "Yes" : "No");
250 bundleGrid.AddRow(" Signature Count:", Bundle.Signatures.Entries.Count.ToString());
251
252 AnsiConsole.Write(bundleGrid);
253 AnsiConsole.WriteLine();
254
255 Grid protectedEntries = new Grid();
256 protectedEntries.AddColumn(new GridColumn().NoWrap());
257
258 protectedEntries.AddRow("Protected Entry Names:");
259
260 foreach (var entryName in Bundle.Manifest.ProtectedEntryNames)
261 {
262 protectedEntries.AddRow($" {entryName}");
263 }
264
265 AnsiConsole.Write(protectedEntries);
266 AnsiConsole.WriteLine();
267
268 Grid manifestEntries = new Grid();
269 manifestEntries.AddColumn(new GridColumn());
270 manifestEntries.AddColumn(new GridColumn().PadLeft(2).Width(18));
271
272 manifestEntries.AddRow("Manifest Entries:");
273 manifestEntries.AddRow(" Entry Name", "Hash");
274
275 foreach (var entry in Bundle.Manifest.Entries)
276 {
277 var entryHash = BitConverter.ToString(entry.Value).Replace("-", "");
278 manifestEntries.AddRow($" {entry.Key}", $"{entryHash[0..8]}..{entryHash.Substring(entryHash.Length - 8)}");
279 }
280
281 AnsiConsole.Write(manifestEntries);
282 AnsiConsole.WriteLine();
283
284 CertificateUtilities.DisplayCertificate(Bundle.Signatures.Entries.Keys.Select(Bundle.GetCertificate).ToArray());
285 }
286
293 protected virtual void RunSign(StatusContext statusContext, X509Certificate2Collection certificates, bool skipVerify)
294 {
295 Logger.LogInformation("Running sign command");
296
297 if (Bundle == null)
298 {
299 throw new ApplicationException("Bundle is not initialized");
300 }
301
302 if (certificates.Count == 0)
303 {
304 Logger.LogWarning("No certificates provided for signing");
305 AnsiConsole.MarkupLine("[red]No certificates provided for signing[/]");
306 return;
307 }
308
309 Logger.LogDebug("Loading bundle");
310 statusContext.Status("[yellow]Loading Bundle[/]");
311 if (!LoadBundle(false)) return;
312
313 int divider = 0;
314 int signs = 0;
315
316 foreach (X509Certificate2 cert in certificates)
317 {
318 if (divider++ > 0) AnsiConsole.WriteLine();
319
320 Logger.LogDebug("Loading certificate information for {Cert}", cert);
321 statusContext.Status("[yellow]Loading certificate informations[/]");
322
323 CertificateUtilities.DisplayCertificate(cert);
324
325 if (!skipVerify)
326 {
327 Logger.LogDebug("Verifying certificate {cert}", cert);
328 statusContext.Status("[yellow]Verifying Certificate[/]");
329
330 bool verifyCert = VerifyCertificate(cert, false);
331 if (!verifyCert)
332 {
333 Logger.LogWarning("Skipping signing with {cert}", cert);
334 continue;
335 }
336 }
337
338 Logger.LogDebug("Acquiring RSA private key for {cert}", cert);
339 statusContext.Status("[yellow]Preparing for signing[/]");
340
341 System.Security.Cryptography.RSA? prvKey = cert.GetRSAPrivateKey();
342 if (prvKey == null)
343 {
344 Logger.LogError("Failed to acquire RSA private key for {cert}", cert);
345 AnsiConsole.MarkupLine($"[{Color.Red}] Failed to Acquire RSA Private Key[/]");
346 continue;
347 }
348
349 Logger.LogDebug("Signing bundle with {cert}", cert);
350 statusContext.Status("[yellow]Signing Bundle[/]");
351
352 Bundle.Sign(cert, prvKey);
353
354 signs++;
355 Logger.LogInformation("Bundle signed with {cert}", cert);
356 AnsiConsole.MarkupLine($"[green] Signing Completed Successfully[/]");
357 }
358
359 if (signs == 0)
360 {
361 Logger.LogWarning("No certificates were suitable for signing");
362 AnsiConsole.MarkupLine("[red]No certificates were suitable for signing[/]");
363 return;
364 }
365
366 Logger.LogInformation("Saving bundle");
367 statusContext.Status("[yellow]Updating Bundle[/]");
368 Bundle.Update();
369
370 Logger.LogInformation("Bundle saved successfully");
371 AnsiConsole.MarkupLine($"[green]File: {Bundle.BundlePath} Saved successfully[/]");
372 }
373
380 protected virtual bool RunVerify(StatusContext statusContext, bool ignoreTime)
381 {
382 Logger.LogInformation("Running verify command");
383
384 if (Bundle == null)
385 {
386 throw new ApplicationException("Bundle is not initialized");
387 }
388
389 Dictionary<string, Color> colorDict = new Dictionary<string, Color>()
390 {
391 ["file_verified"] = Color.MediumSpringGreen,
392 ["file_failed"] = Color.OrangeRed1,
393 ["file_missing"] = Color.Grey70,
394 ["file_error"] = Color.Red3_1,
395 };
396
397 Logger.LogDebug("Loading bundle");
398 statusContext.Status("[yellow]Loading Bundle[/]");
399 if (!LoadBundle()) return false;
400
401 if (Bundle.Signatures.Entries.Count == 0)
402 {
403 Logger.LogError("Bundle is not signed");
404 AnsiConsole.MarkupLine($"[red]The file is not signed[/]");
405 return false;
406 }
407
408 Logger.LogInformation("Starting certificate and signature verification");
409 statusContext.Status("[yellow]Verification Phase 1: Certificates and signatures[/]");
410
411 int verifiedCerts = 0;
412 int divider = 0;
413
414 foreach (string certificateHash in Bundle.Signatures.Entries.Keys)
415 {
416 if (divider++ > 0) AnsiConsole.WriteLine();
417
418 X509Certificate2 certificate = Bundle.GetCertificate(certificateHash);
419
420 Logger.LogDebug("Verifying certificate {cert}", certificate);
421 AnsiConsole.MarkupLine($"Verifying Certificate [{Color.Teal}]{certificate.GetNameInfo(X509NameType.SimpleName, false)}[/] Issued by [{Color.Aqua}]{certificate.GetNameInfo(X509NameType.SimpleName, true)}[/]");
422
423 bool verifyCert = VerifyCertificate(certificate, ignoreTime);
424 if (!verifyCert)
425 {
426 Logger.LogWarning("Skipping signature verification for {cert}", certificate);
427 continue;
428 }
429
430 Logger.LogDebug("Verifying signature for certificate {cert}", certificate);
431 bool verifySign = Bundle.VerifySignature(certificateHash);
432 AnsiConsole.MarkupLine($"[{(verifySign ? Color.Green : Color.Red)}] Signature Verification {(verifySign ? "Successful" : "Failed")}[/]");
433 if (!verifySign)
434 {
435 Logger.LogWarning("Signature verification failed for {cert}", certificate);
436 continue;
437 }
438
439 Logger.LogInformation("Certificate and signature verification successful for {cert}", certificate);
440 verifiedCerts++;
441 }
442
443 AnsiConsole.WriteLine();
444
445 if (verifiedCerts == 0)
446 {
447 Logger.LogWarning("No certificates were verified");
448 AnsiConsole.MarkupLine($"[red]Verification failed[/]");
449 return false;
450 }
451
452 if (verifiedCerts == Bundle.Signatures.Entries.Count)
453 {
454 Logger.LogInformation("All certificates were verified");
455 AnsiConsole.MarkupLine($"[{Color.Green3}]All Certificates were verified[/]");
456 }
457 else
458 {
459 Logger.LogWarning("{verifiedCerts} out of {totalCerts} certificates were verified", verifiedCerts, Bundle.Signatures.Entries.Count);
460 AnsiConsole.MarkupLine($"[{Color.Yellow}]{verifiedCerts} out of {Bundle.Signatures.Entries.Count} Certificates were verified[/]");
461 }
462
463 AnsiConsole.WriteLine();
464
465 Logger.LogInformation("Starting file verification for {fileCount} files in multi-thread mode", Bundle.Manifest.Entries.Count);
466 statusContext.Status("[yellow]Verification Phase 2: Files[/]");
467
468 bool p2Verified = true;
469
470 int fv = 0;
471 int ff = 0;
472 int fm = 0;
473 int fe = 0;
474
475 _ = Parallel.ForEach(Bundle.Manifest.Entries, (entry) =>
476 {
477 bool verifyFile = false;
478
479 Logger.LogDebug("Verifying file {file}", entry.Key);
480
481 try
482 {
483 verifyFile = Bundle.VerifyFile(entry.Key);
484
485 if (verifyFile)
486 {
487 Logger.LogInformation("File {file} verified", entry.Key);
488 Interlocked.Increment(ref fv);
489 }
490 else
491 {
492 Logger.LogWarning("File {file} failed verification", entry.Key);
493 Interlocked.Increment(ref ff);
494 }
495
496 AnsiConsole.MarkupLine($"[{(verifyFile ? colorDict["file_verified"] : colorDict["file_failed"])}]{entry.Key}[/]");
497 }
498 catch (FileNotFoundException)
499 {
500 Logger.LogWarning("File {file} not found", entry.Key);
501 Interlocked.Increment(ref fm);
502 AnsiConsole.MarkupLine($"[{colorDict["file_missing"]}]{entry.Key}[/]");
503 }
504 catch (Exception ex)
505 {
506 Logger.LogError(ex, "Error occurred while verifying file {file}", entry.Key);
507 Interlocked.Increment(ref fe);
508 AnsiConsole.MarkupLine($"[{colorDict["file_error"]}]{entry.Key} - {ex.GetType().Name}: {ex.Message}[/]");
509 }
510
511 if (!verifyFile) p2Verified = false;
512 });
513
514 AnsiConsole.WriteLine();
515
516 if (Bundle.Manifest.Entries.Count != fv)
517 {
518 AnsiConsole.MarkupLine("File Verification Summary");
519 AnsiConsole.MarkupLine($"[{colorDict["file_verified"]}] {fv} Files verified[/]");
520 if (ff > 0) AnsiConsole.MarkupLine($"[{colorDict["file_failed"]}] {ff} Files tampered with[/]");
521 if (fm > 0) AnsiConsole.MarkupLine($"[{colorDict["file_missing"]}] {fm} Files not found[/]");
522 if (fe > 0) AnsiConsole.MarkupLine($"[{colorDict["file_error"]}] {fe} Files encountered with errors[/]");
523
524 AnsiConsole.WriteLine();
525 }
526
527 if (!p2Verified)
528 {
529 Logger.LogWarning("File verification failed");
530 AnsiConsole.MarkupLine($"[red]File Verification Failed[/]");
531 return false;
532 }
533
534 Logger.LogInformation("File verification completed successfully");
535 AnsiConsole.MarkupLine("[green]All Files Verified Successfully[/]");
536
537 return true;
538 }
539
555 protected bool VerifyCertificate(X509Certificate2 certificate, bool ignoreTime)
556 {
557 bool result = VerifyCertificateImpl(certificate, ignoreTime, out X509ChainStatus[] verificationStatuses);
558
559 if (!result)
560 {
561 Utilities.EnumerateStatuses(verificationStatuses);
562 }
563
564 AnsiConsole.MarkupLine($"[{(result ? Color.Green3 : Color.Red)}] Certificate Verification {(result ? "Successful" : "Failed")}[/]");
565 return result;
566 }
567
584 protected bool VerifyCertificateImpl(X509Certificate2 certificate, bool ignoreTime, out X509ChainStatus[] chainStatuses)
585 {
586 if (Bundle == null)
587 {
588 throw new ApplicationException("Bundle is not initialized");
589 }
590
591 List<bool> verificationResults = [];
592 List<X509ChainStatus[]> verificationStatuses = [];
593
594 if (Configuration.Settings["selfsign.enable"] && Configuration.SelfSignedRootCA != null)
595 {
596 verificationResults.Add(SelfSignVerify(certificate, out X509ChainStatus[] selfSigningStatuses));
597 verificationStatuses.Add(selfSigningStatuses);
598 }
599
600 X509ChainPolicy policy = new();
601 policy.ExtraStore.AddRange(Configuration.LoadCertificates(CertificateStore.IntermediateCA));
602
603 if (ignoreTime)
604 {
605 policy.VerificationFlags |= X509VerificationFlags.IgnoreCtlNotTimeValid;
606 }
607
608 if (!verificationResults.Any(x => x))
609 {
610 Logger.LogDebug("Verifying certificate {cert} with system trust store", certificate);
611
612 bool defaultVerification = Bundle.VerifyCertificate(certificate, out X509ChainStatus[] defaultChainStatuses, policy);
613
614 Logger.LogInformation("Certificate verification with system trust store for {cert}: {result}", certificate, defaultVerification);
615
616 verificationResults.Add(defaultVerification);
617 verificationStatuses.Add(defaultChainStatuses);
618 }
619
620 if (Configuration.Settings["trust.enable"] && !verificationResults.Any(x => x) && Configuration.TrustedRootCA.Count > 0)
621 {
622 policy.TrustMode = X509ChainTrustMode.CustomRootTrust;
623 policy.CustomTrustStore.AddRange(Configuration.LoadCertificates(CertificateStore.TrustedRootCA));
624
625 Logger.LogDebug("Verifying certificate {cert} with custom trust store", certificate);
626 bool customVerification = Bundle.VerifyCertificate(certificate, out X509ChainStatus[] customChainStatuses, policy);
627 Logger.LogInformation("Certificate verification with custom trust store for {cert}: {result}", certificate, customVerification);
628
629 verificationResults.Add(customVerification);
630 verificationStatuses.Add(customChainStatuses);
631 }
632
633 chainStatuses = verificationStatuses.Aggregate((prev, next) =>
634 {
635 return prev.Intersect(next).ToArray();
636 });
637
638 return verificationResults.Any(x => x);
639 }
640
641 private bool SelfSignVerify(X509Certificate2 certificate, out X509ChainStatus[] chainStatuses)
642 {
643 if (Bundle == null)
644 {
645 throw new ApplicationException("Bundle is not initialized");
646 }
647
648 chainStatuses = [];
649 X509Certificate2? rootCA;
650
651 if ((rootCA = GetSelfSigningRootCA()) != null)
652 {
653 Logger.LogDebug("Verifying certificate {cert} with self-signing root CA", certificate);
654
655 X509ChainPolicy selfSignPolicy = new X509ChainPolicy();
656 selfSignPolicy.TrustMode = X509ChainTrustMode.CustomRootTrust;
657 selfSignPolicy.CustomTrustStore.Add(rootCA);
658 selfSignPolicy.VerificationFlags |= X509VerificationFlags.IgnoreNotTimeValid;
659 selfSignPolicy.RevocationMode = X509RevocationMode.NoCheck;
660
661 bool selfSignVerification = Bundle.VerifyCertificate(certificate, out chainStatuses, policy: selfSignPolicy);
662 Logger.LogInformation("Certificate verification with self-signing root CA for {cert}: {result}", certificate, selfSignVerification);
663
664 return selfSignVerification;
665 }
666
667 Logger.LogDebug("Self-signing root CA not found");
668 return false;
669 }
670 }
671}
Represents a bundle that holds file hashes and signatures.
Definition Bundle.cs:22
void AddEntry(string path, string destinationPath="./", string? rootPath=null)
Adds a file entry to the bundle.
Definition Bundle.cs:361
string BundlePath
Gets the full path of the bundle file.
Definition Bundle.cs:83
string RootPath
Gets the root path of the bundle.
Definition Bundle.cs:73
void DeleteEntry(string entryName)
Deletes an entry from the bundle.
Definition Bundle.cs:406
void Sign(X509Certificate2 certificate, RSA privateKey)
Signs the bundle with the specified certificate and private key.
Definition Bundle.cs:437
void Update()
Writes changes to the bundle file.
Definition Bundle.cs:731
void LoadFromFile(bool readOnly=true)
Loads the bundle from the file system.
Definition Bundle.cs:276
bool VerifyCertificate(string certificateHash, out X509ChainStatus[] statuses, X509ChainPolicy? policy=null)
Verifies the validity of a certificate using the specified certificate hash.
Definition Bundle.cs:511
X509Certificate2 GetCertificate(string certificateHash)
Gets a certificate from the bundle using the specified certificate hash.
Definition Bundle.cs:571
bool Loaded
Gets a value indicating whether the bundle is loaded.
Definition Bundle.cs:108
Manifest Manifest
Gets the manifest of the bundle.
Definition Bundle.cs:88
bool VerifySignature(string certificateHash)
Verifies the signature of the bundle using the specified certificate hash.
Definition Bundle.cs:486
Signatures Signatures
Gets the signatures of the bundle.
Definition Bundle.cs:93
Provides command definitions and handlers for the EasySign command line interface.
virtual void RunAdd(StatusContext statusContext, string[] files, bool replace, bool recursive, bool continueOnError, bool force)
Runs the add command.
bool LoadBundle(bool readOnly=true)
Loads the bundle from file and handles load errors.
bool VerifyCertificateImpl(X509Certificate2 certificate, bool ignoreTime, out X509ChainStatus[] chainStatuses)
Verifies the certificate using the configured trust stores.
void InitializeBundle(string bundlePath)
Initializes the bundle.
virtual void RunInfo(StatusContext statusContext)
Runs the info command.
ILogger Logger
Gets or sets the logger to use for logging.
bool VerifyCertificate(X509Certificate2 certificate, bool ignoreTime)
Verifies the validity of a certificate.
virtual void RunSign(StatusContext statusContext, X509Certificate2Collection certificates, bool skipVerify)
Runs the sign command.
virtual bool RunVerify(StatusContext statusContext, bool ignoreTime)
Runs the verify command.
Represents a manifest that holds entries of file names and their corresponding hashes.
Definition Manifest.cs:11
SortedDictionary< string, byte[]> Entries
Gets or sets the entries in the manifest as a sorted dictionary.
Definition Manifest.cs:27
static string GetNormalizedEntryName(string path)
Converts the path to an standard zip entry name.
string? UpdatedBy
Gets or sets the full name of the class that updated the manifest.
Definition Manifest.cs:17
bool StoreOriginalFiles
Gets or sets a value indicating whether the files should be stored in the bundle.
Definition Manifest.cs:34
HashSet< string > ProtectedEntryNames
Gets or sets the list of entry names that should be protected by the bundle from accidental modificat...
Definition Manifest.cs:39
Dictionary< string, byte[]> Entries
Gets or sets the signature entries.
Definition Signatures.cs:13
CertificateStore
Enumeration of certificate stores in the CommandProviderConfiguration.