Hi, welcome back,
Sorry it took me so long to write a new post. I'm visiting my colleagues at Milano, and I'm horribly busy these days.
For Windows platforms, below are the only supported methods we can use to digitally sign Authenticode executables:
1) We can use the old SignCode.exe tool (shipped with Authenticode tool for IE or SDK or VS.NET) for signing. SignCode.exe is an old tool from Microsoft to sign Authenticode executables (EXE, DLL, MSI). Newer version of the tool is named SignTool.exe. SignTool.exe is shipped with Microsoft Platform SDK. It is preferred to use the newer SignTool.exe tool. Please note that the command line options for SignTool.exe are different from SignCode.exe.
2) We can programmatically use CryptUIWizDigitalSign API for signing Authenticode executables (MSI, EXE, DLL) (Note this API is only available on Windows XP or above). Additionally, CAPICOM.SignedCode essentially does the same thing.
The following sample shows how to use CryptUIWizDigitalSign in .NET 2.0 through P/Invoke:
<SAMPLE file="Crypto.vb">
Imports System.Runtime.InteropServices Imports System.Security.Cryptography Imports System.ComponentModel Imports System.Windows.Forms Public Class Crypto ' #define CRYPTUI_WIZ_NO_UI 1 Public Const CRYPTUI_WIZ_NO_UI As Int32 = 1 ' #define CRYPTUI_WIZ_DIGITAL_SIGN_SUBJECT_FILE 0x01 Public Const CRYPTUI_WIZ_DIGITAL_SIGN_SUBJECT_FILE As Int32 = 1 ' #define CRYPTUI_WIZ_DIGITAL_SIGN_CERT 0x01 Public Const CRYPTUI_WIZ_DIGITAL_SIGN_CERT As Int32 = 1 ' typedef struct _CRYPTUI_WIZ_DIGITAL_SIGN_INFO { ' DWORD dwSize; ' DWORD dwSubjectChoice; ' union { ' LPCWSTR pwszFileName; ' PCCRYPTUI_WIZ_DIGITAL_SIGN_BLOB_INFO pSignBlobInfo; ' }; ' DWORD dwSigningCertChoice; ' union { ' PCCERT_CONTEXT pSigningCertContext; ' PCCRYPTUI_WIZ_DIGITAL_SIGN_STORE_INFO pSigningCertStore; ' PCCRYPTUI_WIZ_DIGITAL_SIGN_CERT_PVK_INFO pSigningCertPvkInfo; ' }; ' LPCWSTR pwszTimestampURL; ' DWORD dwAdditionalCertChoice; ' PCCRYPTUI_WIZ_DIGITAL_SIGN_EXTENDED_INFO pSignExtInfo; ' } CRYPTUI_WIZ_DIGITAL_SIGN_INFO; <StructLayout(LayoutKind.Sequential)> _ Public Structure CRYPTUI_WIZ_DIGITAL_SIGN_INFO Public dwSize As Int32 Public dwSubjectChoice As Int32 <MarshalAs(UnmanagedType.LPWStr)> Public pwszFileName As String Public dwSigningCertChoice As Int32 Public pSigningCertContext As IntPtr Public pwszTimestampURL As String Public dwAdditionalCertChoice As Int32 Public pSignExtInfo As IntPtr End Structure ' typedef struct _CRYPTUI_WIZ_DIGITAL_SIGN_CONTEXT { ' DWORD dwSize; ' DWORD cbBlob; ' BYTE* pbBlob; ' } CRYPTUI_WIZ_DIGITAL_SIGN_CONTEXT; <StructLayout(LayoutKind.Sequential)> _ Public Structure CRYPTUI_WIZ_DIGITAL_SIGN_CONTEXT Public dwSize As Int32 Public cbBlob As Int32 Public pbBlob As IntPtr End Structure ' BOOL WINAPI CryptUIWizDigitalSign( ' DWORD dwFlags, ' HWND hwndParent, ' LPCWSTR pwszWizardTitle, ' PCCRYPTUI_WIZ_DIGITAL_SIGN_INFO pDigitalSignInfo, ' PCCRYPTUI_WIZ_DIGITAL_SIGN_CONTEXT* ppSignContext ' ); <DllImport("Cryptui.dll", CharSet:=CharSet.Unicode, SetLastError:=True)> _ Public Shared Function CryptUIWizDigitalSign( _ ByVal dwFlags As Int32, _ ByVal hwndParent As IntPtr, _ ByVal pwszWizardTitle As String, _ ByRef pDigitalSignInfo As CRYPTUI_WIZ_DIGITAL_SIGN_INFO, _ ByRef ppSignContext As IntPtr _ ) As Boolean End Function ' BOOL WINAPI CryptUIWizFreeDigitalSignContext( ' PCCRYPTUI_WIZ_DIGITAL_SIGN_CONTEXT pSignContext ' ); <DllImport("Cryptui.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _ Public Shared Function CryptUIWizFreeDigitalSignContext( _ ByVal pSignContext As IntPtr _ ) As Boolean End Function End Class
</SAMPLE>
<SAMPLE file="Module1.vb">
Imports System.ComponentModel Imports System.Runtime.InteropServices Imports SignExe.Crypto Imports System.Security.Cryptography.X509Certificates Imports System.IO Module Module1 Sub Main() ' Variables ' Dim cert As X509Certificate2 Dim digitalSignInfo As CRYPTUI_WIZ_DIGITAL_SIGN_INFO Dim pSignContext As IntPtr Dim pSigningCertContext As IntPtr Dim signContext As CRYPTUI_WIZ_DIGITAL_SIGN_CONTEXT Dim fileOut As FileStream Dim binWriter As BinaryWriter Dim blob() As Byte Try ' Get certificate context ' cert = New X509Certificate2("C:\Test\MyCert.pfx", "") pSigningCertContext = cert.Handle ' Prepare signing info: exe and cert ' digitalSignInfo = New CRYPTUI_WIZ_DIGITAL_SIGN_INFO digitalSignInfo.dwSize = Marshal.SizeOf(digitalSignInfo) digitalSignInfo.dwSubjectChoice = CRYPTUI_WIZ_DIGITAL_SIGN_SUBJECT_FILE digitalSignInfo.pwszFileName = "C:\Test\notepad.exe" digitalSignInfo.dwSigningCertChoice = CRYPTUI_WIZ_DIGITAL_SIGN_CERT digitalSignInfo.pSigningCertContext = pSigningCertContext digitalSignInfo.pwszTimestampURL = vbNullString digitalSignInfo.dwAdditionalCertChoice = 0 digitalSignInfo.pSignExtInfo = IntPtr.Zero ' Sign exe ' If (Not CryptUIWizDigitalSign( _ CRYPTUI_WIZ_NO_UI, _ IntPtr.Zero, _ vbNullString, _ digitalSignInfo, _ pSignContext _ )) Then Throw New Win32Exception(Marshal.GetLastWin32Error(), "CryptUIWizDigitalSign") End If ' Get the blob with the signature ' signContext = Marshal.PtrToStructure(pSignContext, GetType(CRYPTUI_WIZ_DIGITAL_SIGN_CONTEXT)) blob = New Byte(signContext.cbBlob) {} Marshal.Copy(signContext.pbBlob, blob, 0, signContext.cbBlob) ' Store the signature in a new file ' fileOut = File.Open("C:\Test\signature.sig", FileMode.Create) binWriter = New BinaryWriter(fileOut) binWriter.Write(blob) binWriter.Close() fileOut.Close() ' Free blob ' If (Not CryptUIWizFreeDigitalSignContext(pSignContext)) Then Throw New Win32Exception(Marshal.GetLastWin32Error(), "CryptUIWizFreeDigitalSignContext") End If ' We are done Console.WriteLine("Done!!!") Catch ex As Win32Exception ' Any expected errors? ' Console.WriteLine(ex.Message + " error#" + ex.NativeErrorCode.ToString) Catch ex As Exception ' Any unexpected errors? ' Console.WriteLine(ex.Message) End Try ' We are done ' Console.WriteLine("<< Press any key to continue >>") Console.ReadKey() End Sub End Module
I hope this helps.
Cheers,
Alex (Alejandro Campos Magencio)
PS: You may find more info and samples about this on How to sign EXE files with an Authenticode certificate (part 2)
PingBack from http://www.techenclave.com/operating-systems/how-install-unsigned-drivers-windows-7-a-134677.html#post1146018
Tried this but I get a -2147024894 exception return code from the message from:
If (Not CryptUIWizDigitalSign( _
CRYPTUI_WIZ_NO_UI, _
IntPtr.Zero, _
vbNullString, _
digitalSignInfo, _
pSignContext _
)) Then
Throw New Win32Exception(Marshal.GetLastWin32Error(), "CryptUIWizDigitalSign")
End If
What could be the issue? Any ideas?
-2147024894 == 0x80070002 == ERROR_FILE_NOT_FOUND == "The system cannot find the file specified.", so check the paths to the files you are using...