Renamed namespaces and projects from DocumentOperator to DocumentService, updating all references accordingly. Refactored PdfSignatureAppearanceDto and related enums to use properties with init accessors for improved clarity. Removed and re-added IPkcs11SelfTestStatusProvider with updated namespace. Simplified dependency injection by removing DocumentOperatorApplication registration. Updated appsettings.json with a specific AssetsRootPath. Incremented version numbers in project files for a new release. Introduced PdfSignatureClient and IPdfSignatureClient for PDF digital-signing operations. Updated project files to use newer Microsoft.Extensions package versions. Removed all DocumentOperator references, completing the transition to DocumentService. Added new DTOs and enums for PDF signature options and appearance.
120 lines
3.9 KiB
C#
120 lines
3.9 KiB
C#
using DocumentService.Application.Common.Configuration;
|
|
|
|
namespace DocumentService.Infrastructure.Crypt.Services;
|
|
|
|
internal static class Pkcs11InteropBootstrap
|
|
{
|
|
private static readonly object Sync = new();
|
|
private static bool Initialized;
|
|
private const string ProxyRelativePath = "pkcs11\\windows\\proxy\\libpkcs11-proxy.dll";
|
|
private const string ToolRelativePath = "pkcs11\\windows\\opensc\\tools\\pkcs11-tool.exe";
|
|
|
|
public static void EnsureLoaded(Pkcs11Options options)
|
|
{
|
|
if (Initialized)
|
|
return;
|
|
|
|
lock (Sync)
|
|
{
|
|
if (Initialized)
|
|
return;
|
|
|
|
var libraryPath = ResolveLibraryPath(options);
|
|
var toolPath = ResolveToolPath(options);
|
|
options.SetResolvedPaths(libraryPath, toolPath);
|
|
|
|
EnsureNativeDependencySearchPath(options.ResolvedLibraryPath);
|
|
|
|
if (!string.IsNullOrWhiteSpace(options.ProxySocket))
|
|
{
|
|
Environment.SetEnvironmentVariable("PKCS11_PROXY_SOCKET", options.ProxySocket);
|
|
Environment.SetEnvironmentVariable("PKCS11_DAEMON_SOCKET", options.ProxySocket);
|
|
}
|
|
|
|
if (!string.IsNullOrWhiteSpace(options.ResolvedToolPath))
|
|
{
|
|
var toolDir = Path.GetDirectoryName(options.ResolvedToolPath);
|
|
if (!string.IsNullOrWhiteSpace(toolDir))
|
|
EnsurePathContains(toolDir);
|
|
}
|
|
|
|
WarmupWithPkcs11Tool(options);
|
|
Initialized = true;
|
|
}
|
|
}
|
|
|
|
private static string ResolveLibraryPath(Pkcs11Options options)
|
|
{
|
|
var assetsRoot = string.IsNullOrWhiteSpace(options.AssetsRootPath)
|
|
? AppContext.BaseDirectory
|
|
: options.AssetsRootPath;
|
|
|
|
var resolved = Path.Combine(assetsRoot, ProxyRelativePath);
|
|
if (File.Exists(resolved))
|
|
return resolved;
|
|
|
|
throw new FileNotFoundException($"PKCS#11 proxy module not found. Checked path: {resolved}", resolved);
|
|
}
|
|
|
|
private static string? ResolveToolPath(Pkcs11Options options)
|
|
{
|
|
var assetsRoot = string.IsNullOrWhiteSpace(options.AssetsRootPath)
|
|
? AppContext.BaseDirectory
|
|
: options.AssetsRootPath;
|
|
|
|
var resolved = Path.Combine(assetsRoot, ToolRelativePath);
|
|
if (File.Exists(resolved))
|
|
return resolved;
|
|
|
|
return null;
|
|
}
|
|
|
|
private static void WarmupWithPkcs11Tool(Pkcs11Options options)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(options.ResolvedToolPath))
|
|
return;
|
|
|
|
if (!File.Exists(options.ResolvedToolPath))
|
|
return;
|
|
|
|
var process = new System.Diagnostics.Process
|
|
{
|
|
StartInfo = new System.Diagnostics.ProcessStartInfo
|
|
{
|
|
FileName = options.ResolvedToolPath,
|
|
Arguments = $"--module \"{options.ResolvedLibraryPath}\" -L",
|
|
UseShellExecute = false,
|
|
RedirectStandardOutput = true,
|
|
RedirectStandardError = true,
|
|
CreateNoWindow = true
|
|
}
|
|
};
|
|
|
|
process.Start();
|
|
process.WaitForExit(15000);
|
|
}
|
|
|
|
private static void EnsureNativeDependencySearchPath(string libraryPath)
|
|
{
|
|
var directory = Path.GetDirectoryName(libraryPath);
|
|
if (string.IsNullOrWhiteSpace(directory))
|
|
return;
|
|
|
|
EnsurePathContains(directory);
|
|
}
|
|
|
|
private static void EnsurePathContains(string directory)
|
|
{
|
|
var currentPath = Environment.GetEnvironmentVariable("PATH") ?? string.Empty;
|
|
var entries = currentPath.Split(';', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
|
|
if (entries.Any(p => string.Equals(p, directory, StringComparison.OrdinalIgnoreCase)))
|
|
return;
|
|
|
|
var updatedPath = string.IsNullOrWhiteSpace(currentPath)
|
|
? directory
|
|
: directory + ";" + currentPath;
|
|
|
|
Environment.SetEnvironmentVariable("PATH", updatedPath);
|
|
}
|
|
}
|