示例#1
0
        async Task SubmitInternal(HashMode hashMode, string name, string description, string descriptionUrl, IList <string> files)
        {
            logger.LogInformation("Signing OpenVsixSignTool job {0} with {1} files", name, files.Count());

            // Dual isn't supported, use sha256
            var alg = hashMode == HashMode.Sha1 ? HashAlgorithmName.SHA1 : HashAlgorithmName.SHA256;

            var config = new RsaSignConfigurationSet
            {
                FileDigestAlgorithm = alg,
                PkcsDigestAlgorithm = alg,
                SigningCertificate  = await keyVaultService.GetCertificateAsync(),
                Rsa = await keyVaultService.ToRSA()
            };

            try
            {
                var tasks = files.Select(file =>
                {
                    telemetryLogger.OnSignFile(file, signToolName);
                    return(Sign(file, config, keyVaultService.CertificateInfo.TimestampUrl, alg));
                });

                await Task.WhenAll(tasks);
            }
            finally
            {
                config.Rsa?.Dispose();
            }
        }
示例#2
0
        void SubmitInternal(HashMode hashMode, string name, string description, string descriptionUrl, IList <string> files)
        {
            logger.LogInformation("Signing SignTool job {0} with {1} files", name, files.Count());

            var certificate = keyVaultService.GetCertificateAsync().Result;

            using var rsa    = keyVaultService.ToRSA().Result;
            using var signer = new AuthenticodeKeyVaultSigner(rsa, certificate, HashAlgorithmName.SHA256, new TimeStampConfiguration(keyVaultService.CertificateInfo.TimestampUrl, HashAlgorithmName.SHA256, TimeStampType.RFC3161));
            // loop through all of the files here, looking for appx/eappx
            // mark each as being signed and strip appx
            Parallel.ForEach(files, (file, state) =>
            {
                telemetryLogger.OnSignFile(file, signToolName);

                if (!Sign(signer, file, description, descriptionUrl))
                {
                    throw new Exception($"Could not append sign {file}");
                }
            });
        }
        void SubmitInternal(HashMode hashMode, string name, string description, string descriptionUrl, IList <string> files, string filter)
        {
            logger.LogInformation("Signing Mage job {0} with {1} files", name, files.Count());

            var args = "-a sha256RSA";

            if (!string.IsNullOrWhiteSpace(name))
            {
                args += $@" -n ""{name}""";
            }

            var certificate  = keyVaultService.GetCertificateAsync().Result;
            var timeStampUrl = keyVaultService.CertificateInfo.TimestampUrl;

            using (var rsaPrivateKey = keyVaultService.ToRSA()
                                       .Result)
            {
                // This outer loop is for a .clickonce file
                Parallel.ForEach(files, options, (file, state) =>
                {
                    // We need to be explicit about the order these files are signed in. The data files must be signed first
                    // Then the .manifest file
                    // Then the nested clickonce/vsto file
                    // finally the top-level clickonce/vsto file

                    using (var zip = new TemporaryZipFile(file, filter, logger))
                    {
                        // Look for the data files first - these are .deploy files
                        // we need to rename them, sign, then restore the name

                        var deployFilesToSign = zip.FilteredFilesInDirectory.Where(f => ".deploy".Equals(Path.GetExtension(f), StringComparison.OrdinalIgnoreCase))
                                                .ToList();

                        var contentFiles = new List <string>();
                        foreach (var dfile in deployFilesToSign)
                        {
                            // Rename to file without extension
                            var dest = dfile.Replace(".deploy", "");
                            File.Move(dfile, dest);
                            contentFiles.Add(dest);
                        }

                        var filesToSign = contentFiles.ToList(); // copy it since we may add setup.exe

                        var setupExe = zip.FilteredFilesInDirectory.Where(f => ".exe".Equals(Path.GetExtension(f), StringComparison.OrdinalIgnoreCase));
                        filesToSign.AddRange(setupExe);

                        // Safe to call Wait here because we're in a Parallel.ForEach()
                        // sign the inner files
                        signToolAggregate.Value.Submit(hashMode, name, description, descriptionUrl, filesToSign, filter).Wait();

                        // rename the rest of the deploy files since signing the manifest will need them
                        var deployFiles = zip.FilesExceptFiltered.Where(f => ".deploy".Equals(Path.GetExtension(f), StringComparison.OrdinalIgnoreCase))
                                          .ToList();

                        foreach (var dfile in deployFiles)
                        {
                            // Rename to file without extension
                            var dest = dfile.Replace(".deploy", "");
                            File.Move(dfile, dest);
                            contentFiles.Add(dest);
                        }

                        // at this point contentFiles has all deploy files renamed

                        // Inner files are now signed
                        // now look for the manifest file and sign that

                        var manifestFile = zip.FilteredFilesInDirectory.Single(f => ".manifest".Equals(Path.GetExtension(f), StringComparison.OrdinalIgnoreCase));

                        var fileArgs = $@"-update ""{manifestFile}"" {args}";

                        telemetryLogger.OnSignFile(manifestFile, signToolName);
                        if (!Sign(fileArgs, manifestFile, hashMode, rsaPrivateKey, certificate, timeStampUrl))
                        {
                            throw new Exception($"Could not sign {manifestFile}");
                        }

                        // Read the publisher name from the manifest for use below
                        var manifestDoc  = XDocument.Load(manifestFile);
                        var ns           = manifestDoc.Root.GetDefaultNamespace();
                        var publisherEle = manifestDoc.Root.Element(ns + "publisherIdentity");
                        var pubName      = publisherEle.Attribute("name").Value;

                        var publisherParam = "";

                        var dict = DistinguishedNameParser.Parse(pubName);
                        if (dict.TryGetValue("CN", out var cns))
                        {
                            // get the CN. it may be quoted
                            publisherParam = $@"-pub ""{string.Join("+", cns.Select(s => s.Replace("\"", "")))}"" ";
                        }

                        // Now sign the inner vsto/clickonce file
                        // Order by desending length to put the inner one first
                        var clickOnceFilesToSign = zip.FilteredFilesInDirectory
                                                   .Where(f => ".vsto".Equals(Path.GetExtension(f), StringComparison.OrdinalIgnoreCase) ||
                                                          ".application".Equals(Path.GetExtension(f), StringComparison.OrdinalIgnoreCase))
                                                   .Select(f => new { file = f, f.Length })
                                                   .OrderByDescending(f => f.Length)
                                                   .Select(f => f.file)
                                                   .ToList();

                        foreach (var f in clickOnceFilesToSign)
                        {
                            fileArgs = $@"-update ""{f}"" {args} -appm ""{manifestFile}"" {publisherParam}";
                            if (!string.IsNullOrWhiteSpace(descriptionUrl))
                            {
                                fileArgs += $@" -SupportURL {descriptionUrl}";
                            }

                            telemetryLogger.OnSignFile(f, signToolName);
                            if (!Sign(fileArgs, f, hashMode, rsaPrivateKey, certificate, timeStampUrl))
                            {
                                throw new Exception($"Could not sign {f}");
                            }
                        }

                        // restore the deploy files
                        foreach (var dfile in contentFiles)
                        {
                            File.Move(dfile, $"{dfile}.deploy");
                        }

                        zip.Save();
                    }
                });
            }
        }