Question

I am having issues when calling CryptUIWizDigitalSign to programatically sign an executable with our public code signing certificate, without showing any UI. The certificate is a Comodo code signing certificate.

It works fine when the timestamp URL parameter is set to null, but whenever I pass anything other than null in, the call fails (returns zero).

The problem is that without a timestamp, there is no countersignature, and so there are signature validity problems further down the line.

Environment is Windows 7 x64. There is a working standard internet connection. It appears from sniffing the network traffic that no attempt is made by CryptUIWizDigitalSign to contact the timestamp server.

I am calling this from .NET via a PInvoke, but I doubt that would make any difference.

Not a lot on the net about this function...

Dim cert As X509Certificate2 = New X509Certificate2("mycert.pfx", "password")
Dim pSigningCertContext As IntPtr = cert.Handle

Dim digitalSignInfo As CRYPTUI_WIZ_DIGITAL_SIGN_INFO 
    = New CRYPTUI_WIZ_DIGITAL_SIGN_INFO
digitalSignInfo.dwSize = Marshal.SizeOf(digitalSignInfo)
digitalSignInfo.dwSubjectChoice = CRYPTUI_WIZ_DIGITAL_SIGN_SUBJECT_FILE
digitalSignInfo.pwszFileName = "C:\temp\installer.exe"
digitalSignInfo.dwSigningCertChoice = CRYPTUI_WIZ_DIGITAL_SIGN_CERT
digitalSignInfo.pSigningCertContext = pSigningCertContext
digitalSignInfo.pwszTimestampURL = "http://timestamp.comodoca.com/authenticode"
digitalSignInfo.dwAdditionalCertChoice = 0
digitalSignInfo.pSignExtInfo = IntPtr.Zero

If (Not CryptUIWizDigitalSign(CRYPTUI_WIZ_NO_UI, IntPtr.Zero, vbNullString, 
                              digitalSignInfo, pSignContext)) Then
    Throw New Win32Exception(Marshal.GetLastWin32Error(), 
        "CryptUIWizDigitalSign")
End If

The CRYPTUI_WIZ_DIGITAL_SIGN_INFO type is defined as:

<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

Public Const CRYPTUI_WIZ_DIGITAL_SIGN_SUBJECT_FILE As Int32 = 1
Public Const CRYPTUI_WIZ_DIGITAL_SIGN_CERT As Int32 = 1
Public Const CRYPTUI_WIZ_NO_UI As Int32 = 1
Was it helpful?

Solution 2

Fixed - works only within a 32 bit process.

OTHER TIPS

You've applied the MarshalAs attribute on pwszFileName but not pwszTimestampURL, is there any reason for this? They're described identically in the documentation for CRYPTUI_WIZ_DIGITAL_SIGN_INFO :

pwszFileName:

A pointer to a null-terminated Unicode string that contains the path and file name of the file to sign. This member is used if CRYPTUI_WIZ_DIGITAL_SIGN_SUBJECT_FILE is specified for the dwSubjectChoice member.

pwszTimestampURL:

A pointer to a null-terminated Unicode string that contains the URL for the time stamp.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top