2009-02-04 11 views
11

Das Windows SDK wird mit einem Tool namens signtool.exe ausgeliefert, mit dem Sie eine Datei mit einem Zertifikat signieren können. Ich muss dasselbe tun, aber in einem Hintergrunddienst, also bin ich auf der Suche nach einer Bibliothek (vorzugsweise verwalteten Code, aber COM wird tun), um das Gleiche zu tun. Irgendwelche Ideen?API/Bibliothek zum Ersetzen von signtool.exe

Die Antwort gefunden. Hier ist, wie ein X.509-Zertifikat verwenden, um eine Datei in .NET zu unterschreiben:

CmsSigner signer = new CmsSigner(); 
signer.Certificate = new X509Certificate2(certificate); 

SignedCms content = new SignedCms(new ContentInfo(File.ReadAllBytes(fileToSign))); 
content.ComputeSignature(signer, true); 
byte[] signedFile = content.Encode(); 

string signedFileName = fileToSign + ".signed"; 
File.WriteAllBytes(signedFileName, signedFile); 

Console.WriteLine("Signed file: " + signedFileName); 

Hier Zertifikat ist der Pfad zu der PFX-Datei enthält das Zertifikat und fileToSign ist die Datei zu signieren.

Antwort

3

SignTool verwendet CAPICOM, das der COM-Wrapper für die Crypto-API ist. Sie können beide verwenden. Wenn Sie mit CAPICOM arbeiten, können Sie die Informationen here überprüfen.

+0

Gefunden meine Antwort. Dokumentation zur Verwendung der CAPICOM-Bibliothek für die Signierung hier: http://msdn.microsoft.com/en-us/library/aa387760(VS.85).aspx Da die CAPICOM-API veraltet ist, zeigt diese Seite was Die .NET-Ersetzungen sind: http://msdn.microsoft.com/en-us/library/cc778518(VS.85).aspx – Arun

0

Sie können sich nicht einfach darum kümmern? Schreiben Sie eine einfache Batchdatei, die ihr die richtigen Argumente und Eingaben liefert? Das ist mindestens, was wir tun, wenn wir dieses Problem auf einem UNIX-Server sehen.

+0

Wahrscheinlich, weil er nicht davon ausgehen kann, dass es auf dem Zielcomputer und der Lizenz wahrscheinlich bereitgestellt wird verbietet Umverteilung. –

0

Ich bekomme das gleiche Problem wie Sebastien. Wenn man die APIs betrachtet, sieht es so aus, als ob sie umhüllte Nachrichten signieren würden. Authenticode - das Code-Signing, das signtool tut - ist anders, weshalb die EXE nach der Signierung nicht läuft.

Ich bin immer noch auf der Suche nach Alternativen.

0

Für die Google-Reisende ankommen hier:

This MSDN forum thread sagt, es ist ein CryptUIWizDigitalSign API in Windows. Es zeigt auch auf eine blog article von Alejandro Campos Magencio, die eine Beispielimplementierung in VB.NET zeigt.

Da eine C# -Version zu fehlen scheint, habe ich Alejandros Code in C# umgewandelt. Beachten Sie, dass der folgende Code nur (noch) mit Dateien funktioniert.

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

namespace ConsoleApp1 
{ 
    /// <summary> 
    /// Provides code signing functionality via Windows COM Cryptui.dll. 
    /// </summary> 
    class Signer 
    { 

     public const Int32 CRYPTUI_WIZ_NO_UI = 1; 
     public const Int32 CRYPTUI_WIZ_DIGITAL_SIGN_SUBJECT_FILE = 1; 
     public const Int32 CRYPTUI_WIZ_DIGITAL_SIGN_CERT = 1; 

     public struct CRYPTUI_WIZ_DIGITAL_SIGN_INFO 
     { 
      public Int32 dwSize; 
      public Int32 dwSubjectChoice; 
      [MarshalAs(UnmanagedType.LPWStr)] 
      public string pwszFileName; 
      public Int32 dwSigningCertChoice; 
      public IntPtr pSigningCertContext; 
      public string pwszTimestampURL; 
      public Int32 dwAdditionalCertChoice; 
      public IntPtr pSignExtInfo; 
     } 

     [StructLayout(LayoutKind.Sequential)] 
     public struct CRYPTUI_WIZ_DIGITAL_SIGN_CONTEXT 
     { 
      public Int32 dwSize; 
      public Int32 cbBlob; 
      public IntPtr pbBlob; 
     } 

     [DllImport("Cryptui.dll", CharSet = CharSet.Unicode, SetLastError = true)] 
     public static extern bool CryptUIWizDigitalSign(Int32 dwFlags, IntPtr hwndParent, string pwszWizardTitle, ref CRYPTUI_WIZ_DIGITAL_SIGN_INFO pDigitalSignInfo, ref IntPtr ppSignContext); 

     [DllImport("Cryptui.dll", CharSet = CharSet.Auto, SetLastError = true)] 
     public static extern bool CryptUIWizFreeDigitalSignContext(IntPtr pSignContext); 

     /// <summary> 
     /// Signs the executable at the given path with the given code signing certificate. 
     /// </summary> 
     /// <example> 
     /// string certPath = @"C:\certs\CodeSigningTestCert.pfx"; 
     /// string exePath = @"C:\temp\ConsoleApp2ToBeSigned.exe"; 
     /// string certPwd = "myGreatSecurePassword"; 
     ///  
     /// try 
     /// { 
     ///  string resultingSignature = Signer.SignExecutable(certPath, exePath, certPwd); 
     /// } 
     /// catch (Win32Exception ex) 
     /// { 
     ///  Console.WriteLine(ex.Message + ", Native error code: " + ex.NativeErrorCode.ToString()); 
     /// } 
     /// catch (Exception ex) 
     /// { 
     ///  // Any unexpected errors? 
     ///  Console.WriteLine(ex.Message); 
     /// } 
     /// 
     /// </example> 
     /// <param name="certPath">The absolute path to the PFX file to be used for signing the exe file.</param> 
     /// <param name="exePath">The absolute path to the executable to be signed.</param> 
     /// <param name="certPwd">The password for the PFX file.</param> 
     public static string SignExecutable(string certPath, string exePath, string certPwd) 
     { 
      X509Certificate2 cert = default(X509Certificate2); 

      CRYPTUI_WIZ_DIGITAL_SIGN_INFO digitalSignInfo = default(CRYPTUI_WIZ_DIGITAL_SIGN_INFO); 
      CRYPTUI_WIZ_DIGITAL_SIGN_CONTEXT signContext = default(CRYPTUI_WIZ_DIGITAL_SIGN_CONTEXT); 

      IntPtr pSignContext = default(IntPtr); 
      IntPtr pSigningCertContext = default(IntPtr); 

      // Get certificate context 
      cert = new X509Certificate2(certPath, certPwd); 
      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 = exePath; 
      digitalSignInfo.dwSigningCertChoice = CRYPTUI_WIZ_DIGITAL_SIGN_CERT; 
      digitalSignInfo.pSigningCertContext = pSigningCertContext; 
      digitalSignInfo.pwszTimestampURL = null; 
      digitalSignInfo.dwAdditionalCertChoice = 0; 
      digitalSignInfo.pSignExtInfo = IntPtr.Zero; 

      // Sign exe 
      if ((!CryptUIWizDigitalSign(CRYPTUI_WIZ_NO_UI, IntPtr.Zero, null, ref digitalSignInfo, ref pSignContext))) 
       throw new Win32Exception(Marshal.GetLastWin32Error(), "CryptUIWizDigitalSign"); 

      // Get the blob with the signature 
      signContext = (CRYPTUI_WIZ_DIGITAL_SIGN_CONTEXT)Marshal.PtrToStructure(pSignContext, typeof(CRYPTUI_WIZ_DIGITAL_SIGN_CONTEXT)); 
      byte[] blob = new byte[signContext.cbBlob + 1]; 
      Marshal.Copy(signContext.pbBlob, blob, 0, signContext.cbBlob); 

      // Free blob memory 
      if ((!CryptUIWizFreeDigitalSignContext(pSignContext))) 
       throw new Win32Exception(Marshal.GetLastWin32Error(), "CryptUIWizFreeDigitalSignContext"); 

      return System.Text.Encoding.Default.GetString(blob); 
     } 
    } 
} 

Hoffe es hilft!

Verwandte Themen