Skip to content

Commit 65c018f

Browse files
committed
Fix self-signing private key lost
1 parent 979f398 commit 65c018f

File tree

3 files changed

+50
-17
lines changed

3 files changed

+50
-17
lines changed

src/EasySign.Cli/Properties/launchSettings.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
},
1414
"Sign": {
1515
"commandName": "Project",
16-
"commandLineArgs": "sign ."
16+
"commandLineArgs": "sign . -s"
1717
}
1818
}
1919
}

src/EasySign.CommandLine/BundleWorker.cs

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,42 @@ public abstract partial class CommandProvider<T>
1818
/// Initializes the bundle.
1919
/// </summary>
2020
/// <param name="bundlePath">Path of the bundle.</param>
21-
public abstract void InitializeBundle(string bundlePath);
21+
protected abstract void InitializeBundle(string bundlePath);
22+
23+
/// <summary>
24+
/// Loads the bundle from file and handles load errors.
25+
/// </summary>
26+
/// <param name="readOnly">
27+
/// A value indicating whether to load the bundle in read-only mode.
28+
/// </param>
29+
protected bool LoadBundle(bool readOnly = true)
30+
{
31+
if (Bundle == null)
32+
{
33+
throw new ApplicationException("Bundle is not initialized");
34+
}
35+
36+
try
37+
{
38+
Bundle.LoadFromFile(readOnly);
39+
40+
if (!string.IsNullOrEmpty(Bundle.Manifest.UpdatedBy) && Bundle.Manifest.UpdatedBy != Bundle.GetType().FullName)
41+
{
42+
Logger.LogWarning("Bundle was created by a different application");
43+
AnsiConsole.MarkupLine($"[{Color.Orange1}]Warning:[/] Bundle was created by a different application");
44+
}
45+
46+
return true;
47+
}
48+
catch (Exception ex)
49+
{
50+
Logger.LogError(ex, "Failed to load bundle from file: {BundlePath}", Bundle.BundlePath);
51+
AnsiConsole.MarkupLine($"[{Color.Red}]Failed to load bundle from file: {Bundle.BundlePath}[/]");
52+
AnsiConsole.MarkupLine($"[{Color.Red}]Error:[/] {ex.GetType().Name}: {ex.Message}");
53+
}
54+
55+
return false;
56+
}
2257

2358
/// <summary>
2459
/// Runs the add command.
@@ -45,7 +80,8 @@ protected virtual void RunAdd(StatusContext statusContext, bool replace, bool co
4580
{
4681
Logger.LogDebug("A bundle file exists, loading bundle");
4782
statusContext.Status("[yellow]Loading Bundle[/]");
48-
Bundle.LoadFromFile(false);
83+
84+
if (!LoadBundle(false)) return;
4985
}
5086

5187
statusContext.Status("[yellow]Adding Files[/]");
@@ -151,7 +187,7 @@ protected virtual void RunSign(StatusContext statusContext, X509Certificate2Coll
151187

152188
Logger.LogDebug("Loading bundle");
153189
statusContext.Status("[yellow]Loading Bundle[/]");
154-
Bundle.LoadFromFile(false);
190+
if (!LoadBundle(false)) return;
155191

156192
int divider = 0;
157193
int signs = 0;
@@ -194,7 +230,7 @@ protected virtual void RunSign(StatusContext statusContext, X509Certificate2Coll
194230
if (prvKey == null)
195231
{
196232
Logger.LogError("Failed to acquire RSA private key for {cert}", cert);
197-
AnsiConsole.MarkupLine($"[{Color.Green}] Failed to Acquire RSA Private Key[/]");
233+
AnsiConsole.MarkupLine($"[{Color.Red}] Failed to Acquire RSA Private Key[/]");
198234
continue;
199235
}
200236

@@ -246,7 +282,7 @@ protected virtual void RunVerify(StatusContext statusContext)
246282

247283
Logger.LogDebug("Loading bundle");
248284
statusContext.Status("[yellow]Loading Bundle[/]");
249-
Bundle.LoadFromFile();
285+
if (!LoadBundle()) return;
250286

251287
Logger.LogInformation("Starting certificate and signature verification");
252288
statusContext.Status("[yellow]Verification Phase 1: Certificates and signatures[/]");
@@ -414,7 +450,7 @@ protected bool VerifyCertificate(X509Certificate2 certificate)
414450

415451
Logger.LogInformation("Certificate verification with self-signing root CA for {cert}: {result}", certificate, selfSignVerification);
416452

417-
if (!selfSignVerification)
453+
if (selfSignVerification)
418454
{
419455
AnsiConsole.MarkupLine($"[{Color.Green}] Certificate Verification with Self-Signing Root CA Successful[/]");
420456
return true;

src/EasySign.CommandLine/CertificateUtilities.cs

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,8 @@ public static X509Certificate2Collection GetCertificates(string pfxFilePath, str
122122
store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
123123

124124
collection = store.Certificates;
125+
126+
store.Close();
125127
}
126128
catch
127129
{
@@ -201,9 +203,9 @@ public static X509Certificate2 CreateSelfSignedCACertificate(string subjectName)
201203

202204
// Export and re-import to mark the key as exportable (if needed for further signing).
203205
#if NET9_0_OR_GREATER
204-
var cert = X509CertificateLoader.LoadPkcs12(rootCert.Export(X509ContentType.Pfx), null);
206+
var cert = X509CertificateLoader.LoadPkcs12(rootCert.Export(X509ContentType.Pfx), null, X509KeyStorageFlags.EphemeralKeySet | X509KeyStorageFlags.Exportable);
205207
#else
206-
var cert = new X509Certificate2(rootCert.Export(X509ContentType.Pfx));
208+
var cert = new X509Certificate2(rootCert.Export(X509ContentType.Pfx), "", X509KeyStorageFlags.EphemeralKeySet | X509KeyStorageFlags.Exportable);
207209
#endif
208210

209211
return cert;
@@ -220,6 +222,8 @@ public static X509Certificate2 IssueCertificate(string subjectName, X509Certific
220222
{
221223
using (RSA rsa = RSA.Create(2048))
222224
{
225+
_ = rsa.ExportRSAPrivateKey(); // Ensure the RSA key is created.
226+
223227
// Build the certificate request for the issued certificate.
224228
var req = new CertificateRequest(subjectName, rsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
225229

@@ -255,14 +259,7 @@ public static X509Certificate2 IssueCertificate(string subjectName, X509Certific
255259
var issuedCert = req.Create(caCert, DateTimeOffset.UtcNow.AddDays(-1),
256260
DateTimeOffset.UtcNow.AddYears(2), serialNumber);
257261

258-
// Export and re-import to ensure the certificate includes the private key.
259-
#if NET9_0_OR_GREATER
260-
var cert = X509CertificateLoader.LoadPkcs12(issuedCert.Export(X509ContentType.Pfx), null);
261-
#else
262-
var cert = new X509Certificate2(issuedCert.Export(X509ContentType.Pfx));
263-
#endif
264-
265-
return cert;
262+
return issuedCert.CopyWithPrivateKey(rsa);
266263
}
267264
}
268265
}

0 commit comments

Comments
 (0)