public static void SignFileFromDisk(FileInfo filePath) { X509Certificate2 signingCertificate = GetCodeSigningCertificate(); if (signingCertificate == null) { throw new SecurityException("No signing certificate found"); } const DigitalSignFlags flags = DigitalSignFlags.NoUI; DigitalSignInfo dsi = new DigitalSignInfo(); IntPtr certificateHandle = signingCertificate.Handle; try { dsi.pwszFileName = filePath.FullName; dsi.dwSigningCertChoice = DigitalSigningCertificateChoice.Certificate; dsi.dwAdditionalCertChoice = DigitalSignAdditionalCertificateChoice.AddChainNoRoot; dsi.dwSubjectChoice = DigitalSignSubjectChoice.File; dsi.pwszTimestampURL = null; dsi.pSignExtInfo = IntPtr.Zero; dsi.pSigningCertContext = certificateHandle; dsi.dwSize = Marshal.SizeOf(dsi); bool result = CryptUi.CryptUIWizDigitalSign(flags, IntPtr.Zero, "", ref dsi, ref dsi.pSigningCertContext); if (!result) { throw new Win32Exception(Marshal.GetLastWin32Error()); } } finally { //CryptUi.CryptUIWizFreeDigitalSignContext(dsi.pSigningCertContext); //- currently throws, from my reading of http://msdn.microsoft.com/en-us/library/windows/desktop/aa380292%28v=vs.85%29.aspx //I'm not doing any damage by not freeing it. } }
public static extern bool CryptUIWizDigitalSign(DigitalSignFlags dwFlags, IntPtr hwndParent, string pwszWizardTitle, ref DigitalSignInfo pDigitalSignInfo, ref IntPtr ppSignContext);
public void Sign(string fileName, string timeStampUrl) { _signContext = IntPtr.Zero; // Prepare signing info: exe and cert // var digitalSignInfo = new DigitalSignInfo(); digitalSignInfo.dwSize = Marshal.SizeOf(digitalSignInfo); digitalSignInfo.dwSubjectChoice = DigitalSignSubjectChoice.File; digitalSignInfo.pwszFileName = fileName; digitalSignInfo.dwSigningCertChoice = DigitalSigningCertificateChoice.Certificate; digitalSignInfo.pSigningCertContext = _cert.Handle; digitalSignInfo.pwszTimestampURL = timeStampUrl; digitalSignInfo.dwAdditionalCertChoice = DigitalSignAdditionalCertificateChoice.AddChainNoRoot; digitalSignInfo.pSignExtInfo = IntPtr.Zero; // var digitalSignExtendedInfo = new DigitalSignExtendedInfo("description", "http://moerinfo"); // var ptr = Marshal.AllocCoTaskMem(Marshal.SizeOf((object) digitalSignExtendedInfo)); //Marshal.StructureToPtr(digitalSignExtendedInfo, ptr, false); // digitalSignInfo.pSignExtInfo = ptr; // Sign exe // if ((!CryptUi.CryptUIWizDigitalSign(DigitalSignFlags.NoUI, IntPtr.Zero, null, ref digitalSignInfo, ref _signContext))) { var rc = (uint)Marshal.GetLastWin32Error(); if (rc == 0x8007000d) { // this is caused when the timestamp server fails; which seems intermittent for any timestamp service. throw new FailedTimestampException(fileName, timeStampUrl); } throw new DigitalSignFailure(fileName, rc); } }