如何使用 PFX(Bouncy Castle 或其他)以编程方式对可执行文件进行代码签名

2023-11-21

我正在尝试确定使用 Bouncy Castle、托管代码或 C# 中的非托管代码对可执行文件进行代码签名的最佳方法。由于 CAPICOM 现已被弃用,我想如果需要以非托管方式完成,那么 mssign32.dll 中的 SignerSign 方法之一是最好的方法。

这个答案(https://stackoverflow.com/a/3952235/722078)看起来很接近,但它会生成一个 .p7m 文件,该文件虽然看起来大小合适,但无法正确运行(显然在运行之前已重命名为 .exe)。

提问者给出的解决方案在这里(用于替换signtool.exe的API/库)似乎很有前途且易于管理,但就像 Tom Canham 在下面的评论中提到的那样,“这似乎是用于对封装的消息进行签名。Authenticode(signtool 所做的代码签名)是不同的,这就是 EXE 不这样做的原因签字后就跑。”当我使用提问者的解决方案或之前引用的 Bouncy Castle 解决方案进行签名时,我收到与 Tom 相同的错误。

我还没有尝试过的唯一选项在这里给出(https://stackoverflow.com/a/6429860/722078),虽然它看起来很有希望,但我并不肯定它使用“authenticode”代码签名而不是“封装消息”代码签名。这个答案还有一个好处是不使用现在已弃用的 CAPICOM 互操作方法,所以我想我今天将报告使用此方法的结果。如果这是最好的选择,有人可以谈谈两者之间的差异吗?签名者签名, 签名者SignEx, and 签名者SignEx2从 mssign32.dll 导出的函数?我读到 SignerSignEx2 应该与 Windows 8 及更高版本一起使用...

长话短说,我想复制signtool.exe在给定.exe文件、.pfx文件和密码的情况下签署可执行文件的能力,如下所示:

signtool sign /f cert.pfx /p password application.exe

我正在寻找使用authenticode签名以编程方式对可执行文件(PE,如果重要的话)进行代码签名的最佳选择,并且如果可能的话,我更愿意使用充气城堡或托管代码,尽管如果它有效但无效,我会使用非托管代码目前已弃用。

Thanks!


据我所知,SignSigner 和 SignSignerEx 从 Windows XP 开始可用,这是我支持的最古老的操作系统。因为我不需要担心 Windows App Store 发布,所以这个答案仅限于 SignSigner 和 SignSignerEx,尽管 SignSignerEx2 的导入与 SignSignerEx 非常相似,而且我不希望它会导致任何问题。

以下类允许您通过调用使用 .pfx 来签署可执行文件:

SignWithCert(string appPath, string certPath, string certPassword, string timestampUrl);

它还允许您通过调用以下命令使用密钥存储中的证书签署可执行文件:

SignWithThumbPrint(string appPath, string thumbprint, string timestampUrl);

如果您想使用安装到密钥存储中的证书进行签名,您可能需要更新 FindCertByThumbPrint(stringthumbPrint) 以检查比我想检查的更多的密钥存储。 99.5% 的情况下,我们的客户使用 .pfx 进行签名,而不是使用指纹。

为了便于说明,SignWithCert() 使用 SignerSignEx 和 SignerTimeStampEx,而 SignWithThumbPrint() 使用 SignerSign 和 SignerTimeStamp。

它们很容易互换。 SignerSignEx 和 SignerTimeStampEx 返回一个 SIGNER_CONTEXT 指针,并允许您使用 dwFlags 参数修改函数的行为(如果您正在签署可移植的可执行文件)。有效的标志选项列于here。基本上,如果将 0x0 作为 dwFlags 传递给 SignerSignEx,输出将与仅使用 SignerSign 相同。就我而言,我想我将使用 SignerSign,因为我不认为出于任何可以想象的原因我需要指向签名者上下文的指针。

无论如何,这里是班级。这是我第一次在这里发布代码,所以我希望我没有在格式上破坏它。

代码按预期工作,可执行文件运行良好并经过签名,但签名块的二进制输出与signtool.exe 的二进制输出略有不同(在该测试中,两个工具均未使用时间戳)。我将此归因于这样的事实:signtool.exe 似乎使用 CAPICOM 进行签名,而它使用 Mssign32.dll,但总而言之,我对它在最初的一组测试中非常满意。

错误处理显然需要改进。

感谢 GregS 以及之前发布代码示例的所有人。

这是相关的内容。当我有机会时,我将通过评论和改进来更新此块。

更新 1:添加了更好的错误处理和注释,以及 FindCertByThumbprint(字符串指纹)中指纹的一些重新格式化,以允许在 Windows 8 和 Windows 10(公共预览版)上找到证书。当指纹中留有空格时,这些操作系统不会返回匹配项,因此我现在在搜索之前修复它们。

using System;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;

namespace Utilities
{
    internal static class SignTool
    {
        #region Structures

        [StructLayoutAttribute(LayoutKind.Sequential)]
        struct SIGNER_SUBJECT_INFO
        {
            public uint cbSize;
            public IntPtr pdwIndex;
            public uint dwSubjectChoice;
            public SubjectChoiceUnion Union1;
            [StructLayoutAttribute(LayoutKind.Explicit)]
            internal struct SubjectChoiceUnion
            {
                [FieldOffsetAttribute(0)]
                public System.IntPtr pSignerFileInfo;
                [FieldOffsetAttribute(0)]
                public System.IntPtr pSignerBlobInfo;
            };
        }

        [StructLayoutAttribute(LayoutKind.Sequential)]
        struct SIGNER_CERT
        {
            public uint cbSize;
            public uint dwCertChoice;
            public SignerCertUnion Union1;
            [StructLayoutAttribute(LayoutKind.Explicit)]
            internal struct SignerCertUnion
            {
                [FieldOffsetAttribute(0)]
                public IntPtr pwszSpcFile;
                [FieldOffsetAttribute(0)]
                public IntPtr pCertStoreInfo;
                [FieldOffsetAttribute(0)]
                public IntPtr pSpcChainInfo;
            };
            public IntPtr hwnd;
        }

        [StructLayoutAttribute(LayoutKind.Sequential)]
        struct SIGNER_SIGNATURE_INFO
        {
            public uint cbSize;
            public uint algidHash; // ALG_ID
            public uint dwAttrChoice;
            public IntPtr pAttrAuthCode;
            public IntPtr psAuthenticated; // PCRYPT_ATTRIBUTES
            public IntPtr psUnauthenticated; // PCRYPT_ATTRIBUTES
        }

        [StructLayoutAttribute(LayoutKind.Sequential)]
        struct SIGNER_FILE_INFO
        {
            public uint cbSize;
            public IntPtr pwszFileName;
            public IntPtr hFile;
        }

        [StructLayoutAttribute(LayoutKind.Sequential)]
        struct SIGNER_CERT_STORE_INFO
        {
            public uint cbSize;
            public IntPtr pSigningCert; // CERT_CONTEXT
            public uint dwCertPolicy;
            public IntPtr hCertStore;
        }

        [StructLayoutAttribute(LayoutKind.Sequential)]
        struct SIGNER_CONTEXT
        {
            public uint cbSize;
            public uint cbBlob;
            public IntPtr pbBlob;
        }

        [StructLayoutAttribute(LayoutKind.Sequential)]
        struct SIGNER_PROVIDER_INFO
        {
            public uint cbSize;
            public IntPtr pwszProviderName;
            public uint dwProviderType;
            public uint dwKeySpec;
            public uint dwPvkChoice;
            public SignerProviderUnion Union1;
            [StructLayoutAttribute(LayoutKind.Explicit)]
            internal struct SignerProviderUnion
            {
                [FieldOffsetAttribute(0)]
                public IntPtr pwszPvkFileName;
                [FieldOffsetAttribute(0)]
                public IntPtr pwszKeyContainer;
            };
        }

        #endregion

        #region Imports

        [DllImport("Mssign32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        private static extern int SignerSign(
            IntPtr pSubjectInfo,        // SIGNER_SUBJECT_INFO
            IntPtr pSignerCert,         // SIGNER_CERT
            IntPtr pSignatureInfo,      // SIGNER_SIGNATURE_INFO
            IntPtr pProviderInfo,       // SIGNER_PROVIDER_INFO
            string pwszHttpTimeStamp,   // LPCWSTR
            IntPtr psRequest,           // PCRYPT_ATTRIBUTES
            IntPtr pSipData             // LPVOID 
            );

        [DllImport("Mssign32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        private static extern int SignerSignEx(
            uint dwFlags,               // DWORD
            IntPtr pSubjectInfo,        // SIGNER_SUBJECT_INFO
            IntPtr pSignerCert,         // SIGNER_CERT
            IntPtr pSignatureInfo,      // SIGNER_SIGNATURE_INFO
            IntPtr pProviderInfo,       // SIGNER_PROVIDER_INFO
            string pwszHttpTimeStamp,   // LPCWSTR
            IntPtr psRequest,           // PCRYPT_ATTRIBUTES
            IntPtr pSipData,            // LPVOID 
            out SIGNER_CONTEXT ppSignerContext  // SIGNER_CONTEXT
            );

        [DllImport("Mssign32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        private static extern int SignerTimeStamp(
            IntPtr pSubjectInfo,        // SIGNER_SUBJECT_INFO
            string pwszHttpTimeStamp,   // LPCWSTR
            IntPtr psRequest,           // PCRYPT_ATTRIBUTES
            IntPtr pSipData             // LPVOID 
            );

        [DllImport("Mssign32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        private static extern int SignerTimeStampEx(
            uint dwFlags,               // DWORD
            IntPtr pSubjectInfo,        // SIGNER_SUBJECT_INFO
            string pwszHttpTimeStamp,   // LPCWSTR
            IntPtr psRequest,           // PCRYPT_ATTRIBUTES
            IntPtr pSipData,            // LPVOID
            out SIGNER_CONTEXT ppSignerContext  // SIGNER_CONTEXT
            );

        [DllImport("Crypt32.dll", EntryPoint = "CertCreateCertificateContext", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)]
        private static extern IntPtr CertCreateCertificateContext(
            int dwCertEncodingType,
            byte[] pbCertEncoded,
            int cbCertEncoded);

        #endregion

        #region public methods

        // Call SignerSignEx and SignerTimeStampEx for a given .pfx
        public static void SignWithCert(string appPath, string certPath, string certPassword, string timestampUrl)
        {
            IntPtr pSignerCert = IntPtr.Zero;
            IntPtr pSubjectInfo = IntPtr.Zero;
            IntPtr pSignatureInfo = IntPtr.Zero;
            IntPtr pProviderInfo = IntPtr.Zero;

            try
            {
                // Grab the X509Certificate from the .pfx file.
                X509Certificate2 cert = new X509Certificate2(certPath, certPassword);

                pSignerCert = CreateSignerCert(cert);
                pSubjectInfo = CreateSignerSubjectInfo(appPath);
                pSignatureInfo = CreateSignerSignatureInfo();
                pProviderInfo = GetProviderInfo(cert);

                SIGNER_CONTEXT signerContext;

                SignCode(0x0, pSubjectInfo, pSignerCert, pSignatureInfo, pProviderInfo, out signerContext);

                // Only attempt to timestamp if we've got a timestampUrl.
                if (!string.IsNullOrEmpty(timestampUrl))
                {
                    TimeStampSignedCode(0x0, pSubjectInfo, timestampUrl, out signerContext);
                }
            }
            catch (CryptographicException ce)
            {
                string exception;

                // do anything with this useful information?
                switch (Marshal.GetHRForException(ce))
                {
                    case -2146885623:
                        exception = string.Format(@"An error occurred while attempting to load the signing certificate. ""{0}"" does not appear to contain a valid certificate.", certPath);
                        break;
                    case -2147024810:
                        exception = string.Format(@"An error occurred while attempting to load the signing certificate.  The specified password was incorrect.");
                        break;
                    default:
                        exception = string.Format(@"An error occurred while attempting to load the signing certificate.  {0}", ce.Message);
                        break;
                }
            }
            catch (Exception e)
            {
                // do anything with this useful information?
                string exception = e.Message;
            }
            finally
            {
                if (pSignerCert != IntPtr.Zero)
                {
                    Marshal.DestroyStructure(pSignerCert, typeof(SIGNER_CERT));
                }
                if (pSubjectInfo != IntPtr.Zero)
                {
                    Marshal.DestroyStructure(pSubjectInfo, typeof(SIGNER_SUBJECT_INFO));
                }
                if (pSignatureInfo != IntPtr.Zero)
                {
                    Marshal.DestroyStructure(pSignatureInfo, typeof(SIGNER_SIGNATURE_INFO));
                }
                if (pProviderInfo != IntPtr.Zero)
                {
                    Marshal.DestroyStructure(pSignatureInfo, typeof(SIGNER_PROVIDER_INFO));
                }
            }
        }

        // Call SignerSign and SignerTimeStamp for a given thumbprint.
        public static void SignWithThumbprint(string appPath, string thumbprint, string timestampUrl)
        {
            IntPtr pSignerCert = IntPtr.Zero;
            IntPtr pSubjectInfo = IntPtr.Zero;
            IntPtr pSignatureInfo = IntPtr.Zero;
            IntPtr pProviderInfo = IntPtr.Zero;

            try
            {
                pSignerCert = CreateSignerCert(thumbprint);
                pSubjectInfo = CreateSignerSubjectInfo(appPath);
                pSignatureInfo = CreateSignerSignatureInfo();

                SignCode(pSubjectInfo, pSignerCert, pSignatureInfo, pProviderInfo);

                // Only attempt to timestamp if we've got a timestampUrl.
                if (!string.IsNullOrEmpty(timestampUrl))
                {
                    TimeStampSignedCode(pSubjectInfo, timestampUrl);
                }
            }
            catch (CryptographicException ce)
            {
                // do anything with this useful information?
                string exception = string.Format(@"An error occurred while attempting to load the signing certificate.  {0}", ce.Message);
            }
            catch (Exception e)
            {
                // do anything with this useful information?
                string exception = e.Message;
            }
            finally
            {
                if (pSignerCert != IntPtr.Zero)
                {
                    Marshal.DestroyStructure(pSignerCert, typeof(SIGNER_CERT));
                }
                if (pSubjectInfo != IntPtr.Zero)
                {
                    Marshal.DestroyStructure(pSubjectInfo, typeof(SIGNER_SUBJECT_INFO));
                }
                if (pSignatureInfo != IntPtr.Zero)
                {
                    Marshal.DestroyStructure(pSignatureInfo, typeof(SIGNER_SIGNATURE_INFO));
                }
            }
        }

        #endregion

        #region private methods

        private static IntPtr CreateSignerSubjectInfo(string pathToAssembly)
        {
            SIGNER_SUBJECT_INFO info = new SIGNER_SUBJECT_INFO
            {
                cbSize = (uint)Marshal.SizeOf(typeof(SIGNER_SUBJECT_INFO)),
                pdwIndex = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(uint)))
            };
            var index = 0;
            Marshal.StructureToPtr(index, info.pdwIndex, false);

            info.dwSubjectChoice = 0x1; //SIGNER_SUBJECT_FILE
            IntPtr assemblyFilePtr = Marshal.StringToHGlobalUni(pathToAssembly);

            SIGNER_FILE_INFO fileInfo = new SIGNER_FILE_INFO
            {
                cbSize = (uint)Marshal.SizeOf(typeof(SIGNER_FILE_INFO)),
                pwszFileName = assemblyFilePtr,
                hFile = IntPtr.Zero
            };

            info.Union1 = new SIGNER_SUBJECT_INFO.SubjectChoiceUnion
            {
                pSignerFileInfo = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SIGNER_FILE_INFO)))
            };

            Marshal.StructureToPtr(fileInfo, info.Union1.pSignerFileInfo, false);

            IntPtr pSubjectInfo = Marshal.AllocHGlobal(Marshal.SizeOf(info));
            Marshal.StructureToPtr(info, pSubjectInfo, false);

            return pSubjectInfo;
        }

        private static X509Certificate2 FindCertByThumbprint(string thumbprint)
        {
            try
            {
                // Remove spaces convert to upper.  Windows 10 (preview) and Windows 8 will not return a cert
                // unless it is a perfect match with no spaces and all uppercase characters.
                string thumbprintFixed = thumbprint.Replace(" ", string.Empty).ToUpperInvariant();

                // Check common store locations for the corresponding code-signing cert.
                X509Store[] stores = new X509Store[4] { new X509Store(StoreName.My, StoreLocation.CurrentUser),
                                                        new X509Store(StoreName.My, StoreLocation.LocalMachine),
                                                        new X509Store(StoreName.TrustedPublisher, StoreLocation.CurrentUser),
                                                        new X509Store(StoreName.TrustedPublisher, StoreLocation.LocalMachine) };

                foreach (X509Store store in stores)
                {
                    store.Open(OpenFlags.ReadOnly);

                    // Find the cert!
                    X509Certificate2Collection certs = store.Certificates.Find(X509FindType.FindByThumbprint, thumbprintFixed, false);

                    store.Close();

                    // If we didn't find the cert, try the next store.
                    if (certs.Count < 1)
                    {
                        continue;
                    }

                    // Return the cert (first one if there is more than one identical cert in the collection).
                    return certs[0];
                }

                // No cert was found.  Return null.
                throw new Exception(string.Format(@"A certificate matching the thumbprint: ""{0}"" could not be found.  Make sure that a valid certificate matching the provided thumbprint is installed.", thumbprint));
            }
            catch (Exception e)
            {
                throw new Exception(string.Format("{0}", e.Message));
            }
        }

        private static IntPtr CreateSignerCert(X509Certificate2 cert)
        {
            SIGNER_CERT signerCert = new SIGNER_CERT
            {
                cbSize = (uint)Marshal.SizeOf(typeof(SIGNER_CERT)),
                dwCertChoice = 0x2,
                Union1 = new SIGNER_CERT.SignerCertUnion
                {
                    pCertStoreInfo = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SIGNER_CERT_STORE_INFO)))
                },
                hwnd = IntPtr.Zero
            };

            const int X509_ASN_ENCODING = 0x00000001;
            const int PKCS_7_ASN_ENCODING = 0x00010000;

            IntPtr pCertContext = CertCreateCertificateContext(
                X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
                cert.GetRawCertData(),
                cert.GetRawCertData().Length);

            SIGNER_CERT_STORE_INFO certStoreInfo = new SIGNER_CERT_STORE_INFO
            {
                cbSize = (uint)Marshal.SizeOf(typeof(SIGNER_CERT_STORE_INFO)),
                pSigningCert = pCertContext,
                dwCertPolicy = 0x2, // SIGNER_CERT_POLICY_CHAIN
                hCertStore = IntPtr.Zero
            };

            Marshal.StructureToPtr(certStoreInfo, signerCert.Union1.pCertStoreInfo, false);

            IntPtr pSignerCert = Marshal.AllocHGlobal(Marshal.SizeOf(signerCert));
            Marshal.StructureToPtr(signerCert, pSignerCert, false);

            return pSignerCert;
        }

        private static IntPtr CreateSignerCert(string thumbprint)
        {
            SIGNER_CERT signerCert = new SIGNER_CERT
            {
                cbSize = (uint)Marshal.SizeOf(typeof(SIGNER_CERT)),
                dwCertChoice = 0x2,
                Union1 = new SIGNER_CERT.SignerCertUnion
                {
                    pCertStoreInfo = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SIGNER_CERT_STORE_INFO)))
                },
                hwnd = IntPtr.Zero
            };

            const int X509_ASN_ENCODING = 0x00000001;
            const int PKCS_7_ASN_ENCODING = 0x00010000;

            X509Certificate2 cert = FindCertByThumbprint(thumbprint);

            IntPtr pCertContext = CertCreateCertificateContext(
                X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
                cert.GetRawCertData(),
                cert.GetRawCertData().Length);

            SIGNER_CERT_STORE_INFO certStoreInfo = new SIGNER_CERT_STORE_INFO
            {
                cbSize = (uint)Marshal.SizeOf(typeof(SIGNER_CERT_STORE_INFO)),
                pSigningCert = pCertContext,
                dwCertPolicy = 0x2, // SIGNER_CERT_POLICY_CHAIN
                hCertStore = IntPtr.Zero
            };

            Marshal.StructureToPtr(certStoreInfo, signerCert.Union1.pCertStoreInfo, false);

            IntPtr pSignerCert = Marshal.AllocHGlobal(Marshal.SizeOf(signerCert));
            Marshal.StructureToPtr(signerCert, pSignerCert, false);

            return pSignerCert;
        }

        private static IntPtr CreateSignerSignatureInfo()
        {
            SIGNER_SIGNATURE_INFO signatureInfo = new SIGNER_SIGNATURE_INFO
            {
                cbSize = (uint)Marshal.SizeOf(typeof(SIGNER_SIGNATURE_INFO)),
                algidHash = 0x00008004, // CALG_SHA1
                dwAttrChoice = 0x0, // SIGNER_NO_ATTR
                pAttrAuthCode = IntPtr.Zero,
                psAuthenticated = IntPtr.Zero,
                psUnauthenticated = IntPtr.Zero
            };

            IntPtr pSignatureInfo = Marshal.AllocHGlobal(Marshal.SizeOf(signatureInfo));
            Marshal.StructureToPtr(signatureInfo, pSignatureInfo, false);

            return pSignatureInfo;
        }

        private static IntPtr GetProviderInfo(X509Certificate2 cert)
        {
            if (cert == null || !cert.HasPrivateKey)
            {
                return IntPtr.Zero;
            }

            ICspAsymmetricAlgorithm key = (ICspAsymmetricAlgorithm)cert.PrivateKey;
            const int PVK_TYPE_KEYCONTAINER = 2;

            if (key == null)
            {
                return IntPtr.Zero;
            }

            SIGNER_PROVIDER_INFO providerInfo = new SIGNER_PROVIDER_INFO
            {
                cbSize = (uint)Marshal.SizeOf(typeof(SIGNER_PROVIDER_INFO)),
                pwszProviderName = Marshal.StringToHGlobalUni(key.CspKeyContainerInfo.ProviderName),
                dwProviderType = (uint)key.CspKeyContainerInfo.ProviderType,
                dwPvkChoice = PVK_TYPE_KEYCONTAINER,
                Union1 = new SIGNER_PROVIDER_INFO.SignerProviderUnion
                {
                    pwszKeyContainer = Marshal.StringToHGlobalUni(key.CspKeyContainerInfo.KeyContainerName)
                },
            };

            IntPtr pProviderInfo = Marshal.AllocHGlobal(Marshal.SizeOf(providerInfo));
            Marshal.StructureToPtr(providerInfo, pProviderInfo, false);

            return pProviderInfo;
        }

        // Use SignerSign
        private static void SignCode(IntPtr pSubjectInfo, IntPtr pSignerCert, IntPtr pSignatureInfo, IntPtr pProviderInfo)
        {
            int hResult = SignerSign(
                pSubjectInfo,
                pSignerCert,
                pSignatureInfo,
                pProviderInfo,
                null,
                IntPtr.Zero,
                IntPtr.Zero
                );

            if (hResult != 0)
            {
                // See if we can get anything useful.  Jury's still out on this one.
                Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
            }
        }

        // Use SignerSignEx
        private static void SignCode(uint dwFlags, IntPtr pSubjectInfo, IntPtr pSignerCert, IntPtr pSignatureInfo, IntPtr pProviderInfo, out SIGNER_CONTEXT signerContext)
        {

            int hResult = SignerSignEx(
                dwFlags,
                pSubjectInfo,
                pSignerCert,
                pSignatureInfo,
                pProviderInfo,
                null,
                IntPtr.Zero,
                IntPtr.Zero,
                out signerContext
                );

            if (hResult != 0)
            {
                // See if we can get anything useful.  Jury's still out on this one. 
                Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
            }
        }

        // Use SignerTimeStamp
        private static void TimeStampSignedCode(IntPtr pSubjectInfo, string timestampUrl)
        {
            int hResult = SignerTimeStamp(
                pSubjectInfo,
                timestampUrl,
                IntPtr.Zero,
                IntPtr.Zero
                );

            if (hResult != 0)
            {
                // We can't get anything useful from GetHRForLastWin32Error, so let's throw our own.
                //Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
                throw new Exception(string.Format(@"""{0}"" could not be used at this time.  If necessary, check the timestampUrl, internet connection, and try again.", timestampUrl));
            }
        }

        // Use SignerTimeStampEx
        private static void TimeStampSignedCode(uint dwFlags, IntPtr pSubjectInfo, string timestampUrl, out SIGNER_CONTEXT signerContext)
        {
            int hResult = SignerTimeStampEx(
                dwFlags,
                pSubjectInfo,
                timestampUrl,
                IntPtr.Zero,
                IntPtr.Zero,
                out signerContext
                );

            if (hResult != 0)
            {
                // We can't get anything useful from GetHRForLastWin32Error, so let's throw our own.
                //Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
                throw new Exception(string.Format(@"""{0}"" could not be used at this time.  If necessary, check the timestampUrl, internet connection, and try again.", timestampUrl));
            }
        }

        #endregion

    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用 PFX(Bouncy Castle 或其他)以编程方式对可执行文件进行代码签名 的相关文章

随机推荐