Created
August 24, 2019 00:07
-
-
Save dotMorten/293c74dcb956d8b44edfc7317d5f1954 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Requires the following nuget packages: | |
// NuGet.Packaging | |
// OpenVsixSignTool.Core | |
// And built on .NET Framework 4.7.2+ | |
using NuGet.Packaging; | |
using NuGet.Packaging.Signing; | |
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Linq; | |
using System.Security.Cryptography.X509Certificates; | |
using System.Text; | |
using System.Threading; | |
namespace VerifySignatures | |
{ | |
class Program | |
{ | |
static int Main(string[] args) | |
{ | |
bool quietMode = false; | |
int returncode = 0; | |
string path = args[0]; | |
if (args.Contains("-q")) | |
quietMode = true; | |
var opc = OpenVsixSignTool.Core.OpcPackage.Open(path); | |
var signatures = opc.GetSignatures().ToList(); | |
if(signatures.Count == 0) | |
{ | |
WriteLine("ERROR: VSIX not signed: " + path, true); | |
returncode++; | |
} | |
else | |
{ | |
if (!quietMode) WriteLine("VSIX is signed: " + path); | |
foreach (var signature in signatures) | |
{ | |
//TODO: Verify signature is actually valid | |
} | |
} | |
var trustProviders = new ISignatureVerificationProvider[] | |
{ | |
new IntegrityVerificationProvider(), | |
new SignatureTrustAndValidityVerificationProvider(), | |
new AllowListVerificationProvider( | |
new VerificationAllowListEntry[] { }, | |
requireNonEmptyAllowList: false, | |
noMatchErrorMessage: "Strings.Error_NoMatchingCertificate") | |
}; | |
PackageSignatureVerifier verifier = new PackageSignatureVerifier(trustProviders); | |
var verifierSettings = SignedPackageVerifierSettings.GetVerifyCommandDefaultPolicy(); | |
foreach (var item in opc.GetParts()) | |
{ | |
var uri = item.Uri; | |
if(uri.OriginalString.EndsWith(".nupkg")) | |
{ | |
// Verify nuget | |
using (var nuget = new StreamedFile(item)) // item.Open()) | |
{ | |
using (var package = new PackageArchiveReader(nuget.Filename)) | |
{ | |
bool parentWritten = false; | |
VerifySignaturesResult result; | |
try | |
{ | |
result = verifier.VerifySignaturesAsync(package, verifierSettings, CancellationToken.None).Result; | |
} | |
catch(InvalidDataException) | |
{ | |
returncode++; | |
WriteLine($"{uri} - ERROR: NuGet package invalid", true); | |
parentWritten = true; | |
continue; | |
} | |
if(!result.IsSigned) | |
{ | |
returncode++; | |
WriteLine($"{uri} - ERROR: NuGet not signed", true); | |
parentWritten = true; | |
} | |
else if(!result.IsValid) | |
{ | |
returncode++; | |
WriteLine($"{uri} - ERROR: NuGet Signature not valid", true); | |
parentWritten = true; | |
} | |
else | |
{ | |
if (!quietMode) | |
{ | |
WriteLine($"{uri} - OK"); | |
parentWritten = true; | |
} | |
} | |
foreach(var file in package.GetFiles()) | |
{ | |
if (!file.ToLower().EndsWith(".dll")) | |
continue; | |
using (var s = package.GetStream(file)) | |
{ | |
using (var f = new StreamedFile(s)) | |
{ | |
try | |
{ | |
using (var cert = X509Certificate.CreateFromSignedFile(f.Filename)) | |
{ | |
if (!quietMode) Console.WriteLine($"\t{file} - OK"); | |
} | |
} | |
catch (System.Security.Cryptography.CryptographicException) | |
{ | |
returncode++; | |
if (!parentWritten) | |
{ | |
Console.WriteLine(uri); | |
parentWritten = true; | |
} | |
WriteLine($"\t{file} - ERROR: Assembly not signed", true); | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
else if (uri.OriginalString.EndsWith(".dll")) | |
{ | |
// Verify dll | |
using (var f = new StreamedFile(item)) | |
{ | |
try | |
{ | |
using (var cert = X509Certificate.CreateFromSignedFile(f.Filename)) | |
{ | |
if (!quietMode) WriteLine($"{uri} - OK"); | |
} | |
} | |
catch (System.Security.Cryptography.CryptographicException) | |
{ | |
returncode++; | |
WriteLine($"{uri} - ERROR: Assembly not signed", true); | |
} | |
} | |
} | |
} | |
return returncode; | |
} | |
private static void WriteLine(string message, bool isError = false) | |
{ | |
var fc = Console.ForegroundColor; | |
if (isError) | |
Console.ForegroundColor = ConsoleColor.Red; | |
Console.WriteLine(message); | |
if (isError) | |
Console.ForegroundColor = fc; | |
} | |
private class StreamedFile : IDisposable | |
{ | |
string tmp; | |
public StreamedFile(OpenVsixSignTool.Core.OpcPart item) | |
{ | |
using (var s = item.Open()) | |
{ | |
CopyToTempFile(s); | |
} | |
} | |
public StreamedFile(Stream s) | |
{ | |
CopyToTempFile(s); | |
} | |
private void CopyToTempFile(Stream str) | |
{ | |
tmp = Path.GetTempFileName(); | |
using (var file = File.OpenWrite(tmp)) | |
str.CopyTo(file); | |
} | |
public void Dispose() | |
{ | |
File.Delete(tmp); | |
} | |
public string Filename => tmp; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment