Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ OpenVsixSignTool sign --sha1 7213125958254779abbaa5033a12fecdf2c7cdc8 --timestam
This signs the VSIX using a certificate in the certificate store using the SHA1 thumbprint, and uses a SHA256
file digest and SHA256 timestamp digest algorithm.

```shell
OpenVsixSignTool sign --subjectname "My Certificate" --timestamp http://timestamp.digicert.com -ta sha256 -fd sha256 myvsix.vsix
```

This signs the VSIX using a certificate in the certificate store using the subject name.

For more information about usage, use `OpenVsixSignTool sign --help` for more information.

## Core Library
Expand Down
5 changes: 3 additions & 2 deletions src/OpenVsixSignTool/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ internal static int Main(string[] args)
{
signConfiguration.Description = "Signs a VSIX package.";
signConfiguration.HelpOption("-? | -h | --help");
var subjectName = signConfiguration.Option("-n | --subjectname", "Specifies the name of the subject of the signing certificate.", CommandOptionType.SingleValue);
var sha1 = signConfiguration.Option("-s | --sha1", "A hex-encoded SHA-1 thumbprint of the certificate used to sign the opc file.", CommandOptionType.SingleValue);
var pfxPath = signConfiguration.Option("-c | --certificate", "A path to a PFX file to perform the signature.", CommandOptionType.SingleValue);
var password = signConfiguration.Option("-p | --password", "The password for the PFX file.", CommandOptionType.SingleValue);
Expand All @@ -29,9 +30,9 @@ internal static int Main(string[] args)
signConfiguration.OnExecute(() =>
{
var sign = new SignCommand(signConfiguration);
if (sha1.HasValue() || pfxPath.HasValue() || password.HasValue() || pfxPath.HasValue())
if (subjectName.HasValue() || sha1.HasValue() || pfxPath.HasValue() || password.HasValue() || pfxPath.HasValue())
{
return sign.SignAsync(sha1, pfxPath, password, timestamp, timestampAlgorithm, fileDigest, force, file);
return sign.SignAsync(subjectName, sha1, pfxPath, password, timestamp, timestampAlgorithm, fileDigest, force, file);
}
else
{
Expand Down
22 changes: 16 additions & 6 deletions src/OpenVsixSignTool/SignCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public SignCommand(CommandLineApplication signCommandApplication)

internal Task<int> SignAsync
(
CommandOption subjectName,
CommandOption sha1,
CommandOption pfxPath,
CommandOption password,
Expand All @@ -37,22 +38,31 @@ internal Task<int> SignAsync
CommandOption force,
CommandArgument vsixPath)
{
if (!(sha1.HasValue() ^ pfxPath.HasValue()))
if ((sha1.HasValue() ? 1 : 0) + (pfxPath.HasValue() ? 1 : 0) + (subjectName.HasValue() ? 1 : 0) != 1)
{
_signCommandApplication.Out.WriteLine("Either --sha1 or --certificate must be specified, but not both.");
_signCommandApplication.Out.WriteLine("Either --sha1, --subjectname or --certificate must be specified, but not a combination.");
_signCommandApplication.ShowHelp();
return Task.FromResult(EXIT_CODES.INVALID_OPTIONS);
}
X509Certificate2 certificate;
if (sha1.HasValue())
{
certificate = GetCertificateFromCertificateStore(sha1.Value());
certificate = GetCertificateFromCertificateStore(X509FindType.FindByThumbprint, sha1.Value());
if (certificate == null)
{
_signCommandApplication.Out.WriteLine("Unable to locate certificate by thumbprint.");
return Task.FromResult(EXIT_CODES.FAILED);
}
}
else if (subjectName.HasValue())
{
certificate = GetCertificateFromCertificateStore(X509FindType.FindBySubjectName, subjectName.Value());
if (certificate == null)
{
_signCommandApplication.Out.WriteLine("Unable to locate certificate by subject name.");
return Task.FromResult(EXIT_CODES.FAILED);
}
}
else
{
var pfxFilePath = pfxPath.Value();
Expand Down Expand Up @@ -296,12 +306,12 @@ private static AsymmetricAlgorithm GetSigningKeyFromCertificate(X509Certificate2
}
}

private static X509Certificate2 GetCertificateFromCertificateStore(string sha1)
private static X509Certificate2 GetCertificateFromCertificateStore(X509FindType findType, string value)
{
using (var store = new X509Store(StoreName.My, StoreLocation.LocalMachine))
{
store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);
var certificates = store.Certificates.Find(X509FindType.FindByThumbprint, sha1, false);
var certificates = store.Certificates.Find(findType, value, false);
if (certificates.Count > 0)
{
return certificates[0];
Expand All @@ -311,7 +321,7 @@ private static X509Certificate2 GetCertificateFromCertificateStore(string sha1)
using (var store = new X509Store(StoreName.My, StoreLocation.CurrentUser))
{
store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);
var certificates = store.Certificates.Find(X509FindType.FindByThumbprint, sha1, false);
var certificates = store.Certificates.Find(findType, value, false);
if (certificates.Count == 0)
{
return null;
Expand Down