Retired Microsoft Blog disclaimer

This directory is a mirror of retired "Decrypt My World" MSDN blog and is provided as is. All posting authorship and copyrights belong to respective authors.

Posts on this page:

Original URL: https://blogs.msdn.microsoft.com/alejacma/2008/02/20/how-to-sign-exe-files-with-an-authenticode-certificate-vb-net/
Post name: How to sign EXE files with an Authenticode certificate (VB.NET)
Original author: Alejandro Campos Magencio
Posting date: 2008-02-20T03:01:00+00:00


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.0through 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


</SAMPLE>



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)

Original URL: https://blogs.msdn.microsoft.com/alejacma/2008/02/07/how-to-sign-an-xml-and-verify-the-signature-with-net-vb-net/
Post name: How to sign an XML and verify the signature with .NET (VB.NET)
Original author: Alejandro Campos Magencio
Posting date: 2008-02-07T10:28:00+00:00


Hi all,


Today I'm posting a sample which signs an XML with or without a certificate (PFX file) and verifies the signature, all that with .NET and its SignedXml class. I won't include in the sample the code that VS designer includes when I add the textboxes and buttons used in the code. I don't think that's needed to understand the code.



<SAMPLE>

Imports System.Xml
Imports System.Security
Imports System.Security.Cryptography
Imports System.Security.Cryptography.Xml
Imports System.Security.Cryptography.X509Certificates

Public Class Form1
Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "

...

#End Region

Private Sub SignButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SignButton.Click

' Generate a signing key.
'
Dim Key As New RSACryptoServiceProvider

' Create a new XML document.
'
Dim doc As New XmlDocument

' Format using white spaces.
'
doc.PreserveWhitespace = True

' Load the passed XML.
'
doc.Load(TextBox2.Text)

' Create a SignedXml object.
'
Dim signedXml As New SignedXml(doc)

' Add the key to the SignedXml document.
'
signedXml.SigningKey = Key

' Create a reference to be signed.
'
Dim reference As New Reference
reference.Uri = ""

' Add a transformation to the reference.
'
Dim trns As XmlDsigC14NTransform = New XmlDsigC14NTransform
reference.AddTransform(trns)

' Add an enveloped transformation to the reference.
'
Dim env As New XmlDsigEnvelopedSignatureTransform
reference.AddTransform(env)

' Add the reference to the SignedXml object.
'
signedXml.AddReference(reference)

' Add an RSAKeyValue KeyInfo (optional; helps recipient find key to validate).
'
Dim keyInfo As New KeyInfo
keyInfo.AddClause(New RSAKeyValue(CType(Key, RSA)))
signedXml.KeyInfo = keyInfo

' Compute the signature.
'
signedXml.ComputeSignature()

' Get the XML representation of the signature and save
' it to an XmlElement object.
'
Dim xmlDigitalSignature As XmlElement = signedXml.GetXml()

' Append the element to the XML document.
'
doc.DocumentElement.AppendChild(doc.ImportNode(xmlDigitalSignature, True))

If TypeOf doc.FirstChild Is XmlDeclaration Then
doc.RemoveChild(doc.FirstChild)
End If

' Show the signature
'
ToVerifyTextBox.Text = doc.OuterXml
End Sub

Private Sub SignWithCerButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SignWithCerButton.Click

' Variables
'
Dim bResult As Boolean = False
Dim pCertContext As IntPtr = IntPtr.Zero
Dim key As RSA = Nothing
Dim doc As XmlDocument = Nothing
Dim signedXml As SignedXml = Nothing
Dim reference As Reference = Nothing
Dim trns As XmlDsigC14NTransform = Nothing
Dim env As XmlDsigEnvelopedSignatureTransform = Nothing
Dim keyInfo As KeyInfo = Nothing
Dim xmlDigitalSignature As XmlElement = Nothing
Dim cert As X509Certificate2 = Nothing
Dim pass As SecureString = Nothing

' Generate a signing key from the subject certificate.
'
pass = New SecureString()
pass.AppendChar("p")
pass.AppendChar("a")
pass.AppendChar("s")
pass.AppendChar("s")
pass.AppendChar("w")
pass.AppendChar("o")
pass.AppendChar("r")
pass.AppendChar("d")
cert = New X509Certificate2(TextBox1.Text, pass)
key = cert.PrivateKey

' Create a new XML document.
'
doc = New XmlDocument

' Format using white spaces.
'
doc.PreserveWhitespace = True

' Load the passed XML.
'
doc.Load(TextBox2.Text)

' Create a SignedXml object.
'
signedXml = New SignedXml(doc)

' Add the key to the SignedXml document.
'
signedXml.SigningKey = key

' Create a reference to be signed.
'
reference = New Reference
reference.Uri = ""

' Add a transformation to the reference.
'
trns = New XmlDsigC14NTransform
reference.AddTransform(trns)

' Add an enveloped transformation to the reference.
'
env = New XmlDsigEnvelopedSignatureTransform
reference.AddTransform(env)

' Add the reference to the SignedXml object.
'
signedXml.AddReference(reference)

' Add an RSAKeyValue KeyInfo (optional; helps recipient find key to validate).
'
'keyInfo = New KeyInfo
'keyInfo.AddClause(New RSAKeyValue(CType(Key, RSA)))
'signedXml.KeyInfo = keyInfo

' Create a new KeyInfo object.
'
keyInfo = New KeyInfo()

' Load the certificate into a KeyInfoX509Data object
' and add it to the KeyInfo object.
keyInfo.AddClause(New KeyInfoX509Data(cert))

' Add the KeyInfo object to the SignedXml object.
signedXml.KeyInfo = keyInfo

' Compute the signature.
'
signedXml.ComputeSignature()

' Get the XML representation of the signature and save
' it to an XmlElement object.
'
xmlDigitalSignature = signedXml.GetXml()

' Append the element to the XML document.
'
doc.DocumentElement.AppendChild(doc.ImportNode(xmlDigitalSignature, True))

If TypeOf doc.FirstChild Is XmlDeclaration Then
doc.RemoveChild(doc.FirstChild)
End If

' Show the signature
'
ToVerifyTextBox.Text = doc.OuterXml

End Sub

Private Sub VerifyButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles VerifyButton.Click

' Create a new XML document.
'
Dim xmlDocument As New XmlDocument

' Format using white spaces.
'
xmlDocument.PreserveWhitespace = True

' Load the passed XML file into the document.
'
xmlDocument.LoadXml(ToVerifyTextBox.Text)

' Create a new SignedXml object and pass it the XML document class.
'
Dim signedXml As New SignedXml(xmlDocument)

' Find the "Signature" node and create a new XmlNodeList object.
'
Dim nodeList As XmlNodeList = xmlDocument.GetElementsByTagName("Signature", "http://www.w3.org/2000/09/xmldsig#")

' Load the signature node.
'
signedXml.LoadXml(CType(nodeList(0), XmlElement))

' Check the signature and show the result.
'
If signedXml.CheckSignature() Then
MessageBox.Show("Signature verified!")
Else
MessageBox.Show("Invalid signature!!!")
End If

End Sub

End Class


</SAMPLE>


I hope this helps.


Cheers,



Alex (Alejandro Campos Magencio)

Original URL: https://blogs.msdn.microsoft.com/alejacma/2008/01/31/how-to-import-a-certificate-without-user-interaction-c-c/
Post name: How to import a certificate without user interaction (C++ & C#)
Original author: Alejandro Campos Magencio
Posting date: 2008-01-31T06:36:00+00:00


 

Hi, welcome back,

 

Today I'm posting a CryptoAPI sample which uses CryptUIWizImport to import a certificate without any user interaction:

 

 

<SAMPLE Language="C++">

CRYPTUI_WIZ_IMPORT_SRC_INFO importSrc;

memset(&importSrc, 0, sizeof(CRYPTUI_WIZ_IMPORT_SRC_INFO));

importSrc.dwSize = sizeof(CRYPTUI_WIZ_IMPORT_SRC_INFO);

importSrc.dwSubjectChoice = CRYPTUI_WIZ_IMPORT_SUBJECT_FILE;

importSrc.pwszFileName = L"C:\\PathToPFX\\cert.pfx";

importSrc.pwszPassword = L"PasswordToDecryptPFX";

importSrc.dwFlags = CRYPT_EXPORTABLE | CRYPT_USER_PROTECTED;



if (CryptUIWizImport(

  CRYPTUI_WIZ_NO_UI,

  NULL,

  NULL,

  &importSrc,

NULL

) == 0)

{

  printf("CryptUIWizImport error 0x%x\n", GetLastError());

}

 

</SAMPLE>

 

<SAMPLE Language="C#">

using System;

using System.Collections.Generic;

using System.Text;

using System.Runtime.InteropServices;



namespace ImportCertNet

{

 class Program

 {

 public struct CRYPTUI_WIZ_IMPORT_SRC_INFO

 {

 public Int32 dwSize;

 public Int32 dwSubjectChoice;

 [MarshalAs(UnmanagedType.LPWStr)]public String pwszFileName;

 public Int32 dwFlags;

 [MarshalAs(UnmanagedType.LPWStr)]public String pwszPassword;

 }



 [DllImport("CryptUI.dll", CharSet = CharSet.Auto, SetLastError = true)]

 public static extern Boolean CryptUIWizImport(

 Int32 dwFlags,

 IntPtr hwndParent,

 IntPtr pwszWizardTitle,

 ref CRYPTUI_WIZ_IMPORT_SRC_INFO pImportSrc,

 IntPtr hDestCertStore

 );



 public const Int32 CRYPTUI_WIZ_IMPORT_SUBJECT_FILE = 1;

 public const Int32 CRYPT_EXPORTABLE = 0x00000001;

 public const Int32 CRYPT_USER_PROTECTED = 0x00000002;

 public const Int32 CRYPTUI_WIZ_NO_UI = 0x0001;



 static void Main(string[] args)

 {

  CRYPTUI_WIZ_IMPORT_SRC_INFO importSrc = new CRYPTUI_WIZ_IMPORT_SRC_INFO();

  importSrc.dwSize = Marshal.SizeOf(importSrc);

  importSrc.dwSubjectChoice = CRYPTUI_WIZ_IMPORT_SUBJECT_FILE;

  importSrc.pwszFileName = "C:\\alex.pfx";

  importSrc.pwszPassword = "password";

  importSrc.dwFlags = CRYPT_EXPORTABLE | CRYPT_USER_PROTECTED;



  if (!CryptUIWizImport(

 CRYPTUI_WIZ_NO_UI,

  IntPtr.Zero,

  IntPtr.Zero,

  ref importSrc,

  IntPtr.Zero

  ))

  {

  Console.WriteLine("CryptUIWizImport error " + Marshal.GetLastWin32Error());

  }



  Console.WriteLine("<< Press any key to continue >>");

  Console.ReadKey();

 }

 }

}

 

</SAMPLE>

 

 

Note: if you enable High protection mode for the private keys of the certificates via policy, when installing a cert in a machine you will be requested for a password which will be used every time the private key is accessed. When using CryptUIWizImport, a dialog will appear requesting us to enter theHigh protection password, even if we said we don’t want any UI.

 

I hope this helps.

 

Cheers,

 

 

Alex (Alejandro Campos Magencio)

 

Original URL: https://blogs.msdn.microsoft.com/alejacma/2008/01/28/how-to-generate-key-pairs-encrypt-and-decrypt-data-with-cryptoapi/
Post name: How to generate key pairs, encrypt and decrypt data with CryptoAPI
Original author: Alejandro Campos Magencio
Posting date: 2008-01-28T05:18:00+00:00


Hi, welcome back,


Today I'm posting a sample I did some time ago which shows how to generate key pairs, encrypt and decrypt data with C++ and CryptoAPI. The comments in the code should be self-explanatory.


<SAMPLE>

// INCLUDES
#include "stdio.h"
#include "conio.h"
#include "windows.h"
#include "wincrypt.h"
#include "tchar.h"

// FUNCTIONS
int Keys(_TCHAR* strPublicKeyFile, _TCHAR* strPrivateKeyFile);
int Encrypt(_TCHAR* strPublicKeyFile, _TCHAR* strPlainFile, _TCHAR* strEncryptedFile);
int Decrypt(_TCHAR* strPrivateKeyFile, _TCHAR* strEncryptedFile, _TCHAR* strPlainFile);

// Main
int _tmain(int argc, _TCHAR* argv[])
{
int iResult = 0;

if ((argc == 4) && (_tcscmp(argv[1], _T("k")) == 0))
{
// Generate a new key pair
iResult = Keys(argv[2], argv[3]);
}
else if ((argc == 5) && (_tcscmp(argv[1], _T("e")) == 0))
{
// Encrypt
iResult = Encrypt(argv[2], argv[3], argv[4]);
}
else if ((argc == 5) && (_tcscmp(argv[1], _T("d"))== 0))
{
// Decrypt
iResult = Decrypt(argv[2], argv[3], argv[4]);
}
else
{
// Show usage
_tprintf(_T("Usage:\n"));
_tprintf(_T(" - New key pair: EncryptDecrypt k public_key_file private_key_file\n"));
_tprintf(_T(" - Encrypt: EncryptDecrypt e public_key_file plain_file encrypted_file\n"));
_tprintf(_T(" - Decrypt: EncryptDecrypt d private_key_file encrypted_file plain_file\n"));
iResult = 1;
}

_tprintf(_T("\n<< Press any key to continue >>\n"));
_getch();
return iResult;
}
// End of Main

// Keys
int Keys(_TCHAR* strPublicKeyFile, _TCHAR* strPrivateKeyFile)
{
// Variables
HCRYPTPROV hCryptProv = NULL;
HCRYPTKEY hKey = NULL;
DWORD dwPublicKeyLen = 0;
DWORD dwPrivateKeyLen = 0;
BYTE* pbPublicKey = NULL;
BYTE* pbPrivateKey = NULL;
HANDLE hPublicKeyFile = NULL;
HANDLE hPrivateKeyFile = NULL;
DWORD lpNumberOfBytesWritten = 0;

__try
{
// Acquire access to key container
_tprintf(_T("CryptAcquireContext...\n"));
if (!CryptAcquireContext(&hCryptProv, _T("AlejaCMa.EncryptDecrypt"), NULL, PROV_RSA_FULL, 0))
{
// Error
_tprintf(_T("CryptAcquireContext error 0x%x\n"), GetLastError());

// Try to create a new key container
if (!CryptAcquireContext(&hCryptProv, _T("AlejaCMa.EncryptDecrypt"), NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET))
{
// Error
_tprintf(_T("CryptAcquireContext error 0x%x\n"), GetLastError());
return 1;
}
}

// Generate new key pair
_tprintf(_T("CryptGenKey...\n"));
if (!CryptGenKey(hCryptProv, AT_KEYEXCHANGE, CRYPT_ARCHIVABLE, &hKey))
{
// Error
_tprintf(_T("CryptGenKey error 0x%x\n"), GetLastError());
return 1;
}

// Get public key size
_tprintf(_T("CryptExportKey...\n"));
if (!CryptExportKey(hKey, NULL, PUBLICKEYBLOB, 0, NULL, &dwPublicKeyLen))
{
// Error
_tprintf(_T("CryptExportKey error 0x%x\n"), GetLastError());
return 1;
}

// Create a buffer for the public key
_tprintf(_T("malloc...\n"));
if (!(pbPublicKey = (BYTE *)malloc(dwPublicKeyLen)))
{
// Error
_tprintf(_T("malloc error 0x%x\n"), GetLastError());
return 1;
}

// Get public key
_tprintf(_T("CryptExportKey...\n"));
if (!CryptExportKey(hKey, NULL, PUBLICKEYBLOB, 0, pbPublicKey, &dwPublicKeyLen))
{
// Error
_tprintf(_T("CryptExportKey error 0x%x\n"), GetLastError());
return 1;
}

// Get private key size
_tprintf(_T("CryptExportKey...\n"));
if (!CryptExportKey(hKey, NULL, PRIVATEKEYBLOB, 0, NULL, &dwPrivateKeyLen))
{
// Error
_tprintf(_T("CryptExportKey error 0x%x\n"), GetLastError());
return 1;
}

// Create a buffer for the private key
_tprintf(_T("malloc...\n"));
if (!(pbPrivateKey = (BYTE *)malloc(dwPrivateKeyLen)))
{
// Error
_tprintf(_T("malloc error 0x%x\n"), GetLastError());
return 1;
}

// Get private key
_tprintf(_T("CryptExportKey...\n"));
if (!CryptExportKey(hKey, NULL, PRIVATEKEYBLOB, 0, pbPrivateKey, &dwPrivateKeyLen))
{
// Error
_tprintf(_T("CryptExportKey error 0x%x\n"), GetLastError());
return 1;
}

// Create a file to save the public key
_tprintf(_T("CreateFile...\n"));
if ((hPublicKeyFile = CreateFile(
strPublicKeyFile,
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL
)) == INVALID_HANDLE_VALUE)
{
// Error
_tprintf(_T("CreateFile error 0x%x\n"), GetLastError());
return 1;
}

// Write the public key to the file
_tprintf(_T("WriteFile...\n"));
if (!WriteFile(
hPublicKeyFile,
(LPCVOID)pbPublicKey,
dwPublicKeyLen,
&lpNumberOfBytesWritten,
NULL
))
{
// Error
_tprintf(_T("WriteFile error 0x%x\n"), GetLastError());
return 1;
}

// Create a file to save the private key
_tprintf(_T("CreateFile...\n"));
if ((hPrivateKeyFile = CreateFile(
strPrivateKeyFile,
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL
)) == INVALID_HANDLE_VALUE)
{
// Error
_tprintf(_T("CreateFile error 0x%x\n"), GetLastError());
return 1;
}

// Write the private key to the file
_tprintf(_T("WriteFile...\n"));
if (!WriteFile(
hPrivateKeyFile,
(LPCVOID)pbPrivateKey,
dwPrivateKeyLen,
&lpNumberOfBytesWritten,
NULL
))
{
// Error
_tprintf(_T("WriteFile error 0x%x\n"), GetLastError());
return 1;
}

return 0;
}
__finally
{
// Clean up
if (!pbPublicKey) {
_tprintf(_T("free...\n"));
free(pbPublicKey);
}
if (!pbPrivateKey) {
_tprintf(_T("free...\n"));
free(pbPrivateKey);
}
if (hPublicKeyFile) {
_tprintf(_T("CloseHandle...\n"));
CloseHandle(hPublicKeyFile);
}
if (hPrivateKeyFile) {
_tprintf(_T("CloseHandle...\n"));
CloseHandle(hPrivateKeyFile);
}
if (hKey) {
_tprintf(_T("CryptDestroyKey...\n"));
CryptDestroyKey(hKey);
}
if (hCryptProv) {
_tprintf(_T("CryptReleaseContext...\n"));
CryptReleaseContext(hCryptProv, 0);
}
}
}
// End of Keys

// Encrypt
int Encrypt(_TCHAR* strPublicKeyFile, _TCHAR* strPlainFile, _TCHAR* strEncryptedFile)
{
// Variables
HCRYPTPROV hCryptProv = NULL;
HCRYPTKEY hKey = NULL;
DWORD dwPublicKeyLen = 0;
DWORD dwDataLen = 0;
DWORD dwEncryptedLen = 0;
BYTE* pbPublicKey = NULL;
BYTE* pbData = NULL;
HANDLE hPublicKeyFile = NULL;
HANDLE hEncryptedFile = NULL;
HANDLE hPlainFile = NULL;
DWORD lpNumberOfBytesWritten = 0;

__try
{
// Acquire access to key container
_tprintf(_T("CryptAcquireContext...\n"));
if (!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
{
// Error
_tprintf(_T("CryptAcquireContext error 0x%x\n"), GetLastError());
return 1;
}

// Open public key file
_tprintf(_T("CreateFile...\n"));
if ((hPublicKeyFile = CreateFile(
strPublicKeyFile,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN,
NULL
)) == INVALID_HANDLE_VALUE)
{
// Error
_tprintf(_T("CreateFile error 0x%x\n"), GetLastError());
return 1;
}

// Get file size
_tprintf(_T("GetFileSize...\n"));
if ((dwPublicKeyLen = GetFileSize(hPublicKeyFile, NULL)) == INVALID_FILE_SIZE)
{
// Error
_tprintf(_T("GetFileSize error 0x%x\n"), GetLastError());
return 1;
}

// Create a buffer for the public key
_tprintf(_T("malloc...\n"));
if (!(pbPublicKey = (BYTE *)malloc(dwPublicKeyLen)))
{
// Error
_tprintf(_T("malloc error 0x%x\n"), GetLastError());
return 1;
}

// Read public key
_tprintf(_T("ReadFile...\n"));
if (!ReadFile(hPublicKeyFile, pbPublicKey, dwPublicKeyLen, &dwPublicKeyLen, NULL))
{
// Error
_tprintf(_T("ReadFile error 0x%x\n"), GetLastError());
return 1;
}

// Import public key
_tprintf(_T("CryptImportKey...\n"));
if (!CryptImportKey(hCryptProv, pbPublicKey, dwPublicKeyLen, 0, 0, &hKey))
{
// Error
_tprintf(_T("CryptImportKey error 0x%x\n"), GetLastError());
return 1;
}

// Open plain text file
_tprintf(_T("CreateFile...\n"));
if ((hPlainFile = CreateFile(
strPlainFile,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN,
NULL
)) == INVALID_HANDLE_VALUE)
{
// Error
_tprintf(_T("CreateFile error 0x%x\n"), GetLastError());
return 1;
}

// Get file size
_tprintf(_T("GetFileSize...\n"));
if ((dwDataLen = GetFileSize(hPlainFile, NULL)) == INVALID_FILE_SIZE)
{
// Error
_tprintf(_T("GetFileSize error 0x%x\n"), GetLastError());
return 1;
}

// Create a buffer for the plain text
_tprintf(_T("malloc...\n"));
if (!(pbData = (BYTE *)malloc(dwDataLen)))
{
// Error
_tprintf(_T("malloc error 0x%x\n"), GetLastError());
return 1;
}

// Read plain text
_tprintf(_T("ReadFile...\n"));
if (!ReadFile(hPlainFile, pbData, dwDataLen, &dwDataLen, NULL))
{
// Error
_tprintf(_T("ReadFile error 0x%x\n"), GetLastError());
return 1;
}

// Get lenght for encrypted data
if (!CryptEncrypt(hKey, NULL, TRUE, 0, NULL, &dwEncryptedLen, 0))
{
// Error
_tprintf(_T("CryptEncrypt error 0x%x\n"), GetLastError());
return 1;
}

// Create a buffer for encrypted data
_tprintf(_T("malloc...\n"));
if (!(pbData = (BYTE *)realloc(pbData, dwEncryptedLen)))
{
// Error
_tprintf(_T("malloc error 0x%x\n"), GetLastError());
return 1;
}

// Encrypt data
if (!CryptEncrypt(hKey, NULL, TRUE, 0, pbData, &dwDataLen, dwEncryptedLen))
{
// Error
_tprintf(_T("CryptEncrypt error 0x%x\n"), GetLastError());
return 1;
}

// Create a file to save the encrypted data
_tprintf(_T("CreateFile...\n"));
if ((hEncryptedFile = CreateFile(
strEncryptedFile,
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL
)) == INVALID_HANDLE_VALUE)
{
// Error
_tprintf(_T("CreateFile error 0x%x\n"), GetLastError());
return 1;
}

// Write the public key to the file
_tprintf(_T("WriteFile...\n"));
if (!WriteFile(
hEncryptedFile,
(LPCVOID)pbData,
dwDataLen,
&lpNumberOfBytesWritten,
NULL
))
{
// Error
_tprintf(_T("WriteFile error 0x%x\n"), GetLastError());
return 1;
}

return 0;
}
__finally
{
// Clean up
if (!pbPublicKey) {
_tprintf(_T("free...\n"));
free(pbPublicKey);
}
if (!pbData) {
_tprintf(_T("free...\n"));
free(pbData);
}
if (hPublicKeyFile) {
_tprintf(_T("CloseHandle...\n"));
CloseHandle(hPublicKeyFile);
}
if (hPlainFile) {
_tprintf(_T("CloseHandle...\n"));
CloseHandle(hPlainFile);
}
if (hEncryptedFile) {
_tprintf(_T("CloseHandle...\n"));
CloseHandle(hEncryptedFile);
}
if (hKey) {
_tprintf(_T("CryptDestroyKey...\n"));
CryptDestroyKey(hKey);
}
if (hCryptProv) {
_tprintf(_T("CryptReleaseContext...\n"));
CryptReleaseContext(hCryptProv, 0);
}
}
}
// End of Encrypt

// Decrypt
int Decrypt(_TCHAR* strPrivateKeyFile, _TCHAR* strEncryptedFile, _TCHAR* strPlainFile)
{
// Variables
HCRYPTPROV hCryptProv = NULL;
HCRYPTKEY hKey = NULL;
DWORD dwPrivateKeyLen = 0;
DWORD dwDataLen = 0;
BYTE* pbPrivateKey = NULL;
BYTE* pbData = NULL;
HANDLE hPrivateKeyFile = NULL;
HANDLE hEncryptedFile = NULL;
HANDLE hPlainFile = NULL;
DWORD lpNumberOfBytesWritten = 0;

__try
{
// Acquire access to key container
_tprintf(_T("CryptAcquireContext...\n"));
if (!CryptAcquireContext(&hCryptProv, _T("AlejaCMa.EncryptDecrypt"), NULL, PROV_RSA_FULL, 0))
{
// Error
_tprintf(_T("CryptAcquireContext error 0x%x\n"), GetLastError());

// Try to create a new key container
if (!CryptAcquireContext(&hCryptProv, _T("AlejaCMa.EncryptDecrypt"), NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET))
{
// Error
_tprintf(_T("CryptAcquireContext error 0x%x\n"), GetLastError());
return 1;
}
}

// Open private key file
_tprintf(_T("CreateFile...\n"));
if ((hPrivateKeyFile = CreateFile(
strPrivateKeyFile,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN,
NULL
)) == INVALID_HANDLE_VALUE)
{
// Error
_tprintf(_T("CreateFile error 0x%x\n"), GetLastError());
return 1;
}

// Get file size
_tprintf(_T("GetFileSize...\n"));
if ((dwPrivateKeyLen = GetFileSize(hPrivateKeyFile, NULL)) == INVALID_FILE_SIZE)
{
// Error
_tprintf(_T("GetFileSize error 0x%x\n"), GetLastError());
return 1;
}

// Create a buffer for the private key
_tprintf(_T("malloc...\n"));
if (!(pbPrivateKey = (BYTE *)malloc(dwPrivateKeyLen)))
{
// Error
_tprintf(_T("malloc error 0x%x\n"), GetLastError());
return 1;
}

// Read private key
_tprintf(_T("ReadFile...\n"));
if (!ReadFile(hPrivateKeyFile, pbPrivateKey, dwPrivateKeyLen, &dwPrivateKeyLen, NULL))
{
// Error
_tprintf(_T("ReadFile error 0x%x\n"), GetLastError());
return 1;
}

// Import private key
_tprintf(_T("CryptImportKey...\n"));
if (!CryptImportKey(hCryptProv, pbPrivateKey, dwPrivateKeyLen, 0, 0, &hKey))
{
// Error
_tprintf(_T("CryptImportKey error 0x%x\n"), GetLastError());
return 1;
}

// Open encrypted file
_tprintf(_T("CreateFile...\n"));
if ((hEncryptedFile = CreateFile(
strEncryptedFile,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN,
NULL
)) == INVALID_HANDLE_VALUE)
{
// Error
_tprintf(_T("CreateFile error 0x%x\n"), GetLastError());
return 1;
}

// Get file size
_tprintf(_T("GetFileSize...\n"));
if ((dwDataLen = GetFileSize(hEncryptedFile, NULL)) == INVALID_FILE_SIZE)
{
// Error
_tprintf(_T("GetFileSize error 0x%x\n"), GetLastError());
return 1;
}

// Create a buffer for the encrypted data
_tprintf(_T("malloc...\n"));
if (!(pbData = (BYTE *)malloc(dwDataLen)))
{
// Error
_tprintf(_T("malloc error 0x%x\n"), GetLastError());
return 1;
}

// Read encrypted data
_tprintf(_T("ReadFile...\n"));
if (!ReadFile(hEncryptedFile, pbData, dwDataLen, &dwDataLen, NULL))
{
// Error
_tprintf(_T("ReadFile error 0x%x\n"), GetLastError());
return 1;
}

// Get lenght for plain text
if (!CryptDecrypt(hKey, NULL, TRUE, 0, pbData, &dwDataLen))
{
// Error
_tprintf(_T("CryptDecrypt error 0x%x\n"), GetLastError());
return 1;
}

// Create a file to save the plain text
_tprintf(_T("CreateFile...\n"));
if ((hPlainFile = CreateFile(
strPlainFile,
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL
)) == INVALID_HANDLE_VALUE)
{
// Error
_tprintf(_T("CreateFile error 0x%x\n"), GetLastError());
return 1;
}

// Write the plain text the file
_tprintf(_T("WriteFile...\n"));
if (!WriteFile(
hPlainFile,
(LPCVOID)pbData,
dwDataLen,
&lpNumberOfBytesWritten,
NULL
))
{
// Error
_tprintf(_T("WriteFile error 0x%x\n"), GetLastError());
return 1;
}

return 0;
}
__finally
{
// Clean up
if (!pbPrivateKey) {
_tprintf(_T("free...\n"));
free(pbPrivateKey);
}
if (!pbData) {
_tprintf(_T("free...\n"));
free(pbData);
}
if (hPrivateKeyFile) {
_tprintf(_T("CloseHandle...\n"));
CloseHandle(hPrivateKeyFile);
}
if (hEncryptedFile) {
_tprintf(_T("CloseHandle...\n"));
CloseHandle(hEncryptedFile);
}
if (hPlainFile) {
_tprintf(_T("CloseHandle...\n"));
CloseHandle(hPlainFile);
}
if (hKey) {
_tprintf(_T("CryptDestroyKey...\n"));
CryptDestroyKey(hKey);
}
if (hCryptProv) {
_tprintf(_T("CryptReleaseContext...\n"));
CryptReleaseContext(hCryptProv, 0);
}
}
}
// End of Decrypt


</SAMPLE>



Take a look to the following article for more info on these APIs: The Cryptography API, or How to Keep a Secret.



I hope this helps.


Cheers,



Alex (Alejandro Campos Magencio)



Original URL: https://blogs.msdn.microsoft.com/alejacma/2008/01/23/how-to-sign-and-verify-with-cryptoapi-and-a-user-certificate/
Post name: How to sign and verify with CryptoAPI and a user certificate
Original author: Alejandro Campos Magencio
Posting date: 2008-01-23T06:35:00+00:00


Hi, welcome back,


Today I will show how to sign data and verify that signature using CryptoAPI and a certificate from our Personal store. The comments in the code should help to understand it. Remember that this is just a sample, and some more cleanup would be needed incase of error, for instance.


<SAMPLE>

// Includes
#include <stdio.h>
#include <conio.h>
#include <windows.h>
#include <wincrypt.h>

// Defines
#define CERT_PERSONAL_STORE_NAME L"My"
#define CERT_OTHER_PEOPLE_STORE_NAME L"AddressBook"
#define MY_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
#define BUFSIZE 1024

// Local functions
void Sign(wchar_t * SignerName, wchar_t * DataFileName, wchar_t * SignatureFileName);
void Verify(wchar_t * SignerName, wchar_t * SignatureFileName, wchar_t * DataFileName);

// ShowUsageAndExit
void ShowUsageAndExit()
{
wprintf(L"Usage:\n");
wprintf(L" - To sign: SignVerify s signer_name data_file signature_file\n");
wprintf(L" - To verify: SignVerify v signer_name data_file signature_file\n");
wprintf(L"\n<< Press any key to continue >>\n");
_getch();
exit(1);

}
// End of ShowUsageAndExit

// CheckError
void CheckError(BOOL condition, wchar_t * message)
{
wprintf(message);
if (condition)
{
wprintf(L"SUCCESS\n");
}
else
{
// TODO: Some cleanup
wprintf(L"FAILURE (0x%x)\n", GetLastError());
wprintf(L"\n<< Press any key to continue >>\n");
_getch();
exit(1);
}
}
// End CheckError

// Main
void wmain(int argc, wchar_t * argv[])
{

// Usage
if (argc != 5) {
ShowUsageAndExit();
}

if (!wcscmp(argv[1], L"s"))
{
// Sign
Sign(argv[2], argv[3], argv[4]);
}
else if (!wcscmp(argv[1], L"v"))
{
// Verify
Verify(argv[2], argv[3], argv[4]);
}
else
{
// Error
ShowUsageAndExit();
}

// The end
wprintf(L"\n<< Press any key to continue >>\n");
_getch();

}
// End of main

// Sign
void Sign(wchar_t * SignerName, wchar_t * DataFileName, wchar_t * SignatureFileName)
{
// Variables
HCERTSTORE hStoreHandle = NULL;
PCCERT_CONTEXT pSignerCert = NULL;
HCRYPTPROV hCryptProv = NULL;
DWORD dwKeySpec = 0;
HCRYPTHASH hHash = NULL;
HANDLE hDataFile = NULL;
BOOL bResult = FALSE;
BYTE rgbFile[BUFSIZE];
DWORD cbRead = 0;
DWORD dwSigLen = 0;
BYTE * pbSignature = NULL;
HANDLE hSignatureFile = NULL;
DWORD lpNumberOfBytesWritten = 0;

wprintf(L"SIGNING\n\n");

// Open the certificate store.
hStoreHandle = CertOpenStore(
CERT_STORE_PROV_SYSTEM,
0,
NULL,
CERT_SYSTEM_STORE_CURRENT_USER,
CERT_PERSONAL_STORE_NAME
);
CheckError((BOOL)hStoreHandle, L"CertOpenStore....................... ");

// Get signer's certificate with access to private key.
do {
// Get a certificate that matches the search criteria
pSignerCert = CertFindCertificateInStore(
hStoreHandle,
MY_TYPE,
0,
CERT_FIND_SUBJECT_STR,
SignerName,
pSignerCert
);
CheckError((BOOL)pSignerCert, L"CertFindCertificateInStore.......... ");

// Get the CSP, and check if we can sign with the private key
bResult = CryptAcquireCertificatePrivateKey(
pSignerCert,
0,
NULL,
&hCryptProv,
&dwKeySpec,
NULL
);
CheckError(bResult, L"CryptAcquireCertificatePrivateKey... ");

} while ((dwKeySpec & AT_SIGNATURE) != AT_SIGNATURE);

// Create the hash object.
bResult = CryptCreateHash(
hCryptProv,
CALG_MD5,
0,
0,
&hHash
);
CheckError(bResult, L"CryptCreateHash..................... ");

// Open the file with the content to be signed
hDataFile = CreateFileW(DataFileName,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN,
NULL
);
CheckError((hDataFile != INVALID_HANDLE_VALUE), L"CreateFile.......................... ");

// Compute the cryptographic hash of the data.
while (bResult = ReadFile(hDataFile, rgbFile, BUFSIZE, &cbRead, NULL))
{
if (cbRead == 0)
{
break;
}
CheckError(bResult, L"ReadFile............................ ");

bResult = CryptHashData(
hHash,
rgbFile,
cbRead,
0
);
CheckError(bResult, L"CryptHashData....................... ");

}
CheckError(bResult, L"ReadFile............................ ");

// Sign the hash object
dwSigLen = 0;
bResult = CryptSignHash(
hHash,
AT_SIGNATURE,
NULL,
0,
NULL,
&dwSigLen
);
CheckError(bResult, L"CryptSignHash....................... ");

pbSignature = (BYTE *)malloc(dwSigLen);
CheckError((BOOL)pbSignature, L"malloc.............................. ");

bResult = CryptSignHash(
hHash,
AT_SIGNATURE,
NULL,
0,
pbSignature,
&dwSigLen
);
CheckError(bResult, L"CryptSignHash....................... ");

// Create a file to save the signature
hSignatureFile = CreateFileW(
SignatureFileName,
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL
);
CheckError((hSignatureFile != INVALID_HANDLE_VALUE), L"CreateFile.......................... ");

// Write the signature to the file
bResult = WriteFile(
hSignatureFile,
(LPCVOID)pbSignature,
dwSigLen,
&lpNumberOfBytesWritten,
NULL
);
CheckError(bResult, L"WriteFile........................... ");

// Clean up and free memory.
free(pbSignature);

CloseHandle(hDataFile);
CloseHandle(hSignatureFile);

bResult = CryptDestroyHash(hHash);
CheckError(bResult, L"CryptDestroyHash.................... ");

bResult = CertFreeCertificateContext(pSignerCert);
CheckError(bResult, L"CertFreeCertificateContext.......... ");

bResult = CertCloseStore(
hStoreHandle,
CERT_CLOSE_STORE_CHECK_FLAG
);
CheckError(bResult, L"CertCloseStore...................... ");

}
// End of Sign

// Verify
void Verify(wchar_t * SignerName, wchar_t * DataFileName, wchar_t * SignatureFileName)
{
// Variables
HCERTSTORE hStoreHandle = NULL;
PCCERT_CONTEXT pSignerCert = NULL;
DWORD dwKeySpec = 0;
HCRYPTPROV hCryptProv = NULL;
HCRYPTHASH hHash = NULL;
HANDLE hDataFile = NULL;
BOOL bResult = FALSE;
BYTE rgbFile[BUFSIZE];
DWORD cbRead = 0;
HANDLE hSignatureFile = NULL;
BYTE * pbBinary = NULL;
DWORD cbBinary = 0;
HCRYPTKEY hPubKey = NULL;

wprintf(L"VERIFYING\n\n");

// Open the certificate store.
hStoreHandle = CertOpenStore(
CERT_STORE_PROV_SYSTEM,
0,
NULL,
CERT_SYSTEM_STORE_CURRENT_USER,
CERT_PERSONAL_STORE_NAME
);
CheckError((BOOL)hStoreHandle, L"CertOpenStore....................... ");

// Get a certificate that matches the search criteria
pSignerCert = CertFindCertificateInStore(
hStoreHandle,
MY_TYPE,
0,
CERT_FIND_SUBJECT_STR,
SignerName,
pSignerCert
);
CheckError((BOOL)pSignerCert, L"CertFindCertificateInStore.......... ");

// Get the CSP
bResult = CryptAcquireContext(
&hCryptProv,
NULL,
NULL,
PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT
);
CheckError(bResult, L"CryptAcquireContext................. ");

// Create the hash object.
bResult = CryptCreateHash(
hCryptProv,
CALG_MD5,
0,
0,
&hHash
);
CheckError(bResult, L"CryptCreateHash..................... ");

// Open the file with the content that was signed.
hDataFile = CreateFileW(
DataFileName,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN,
NULL
);
CheckError((hDataFile != INVALID_HANDLE_VALUE), L"CreateFile.......................... ");

// Compute the cryptographic hash of the data.
while (bResult = ReadFile(hDataFile, rgbFile, BUFSIZE, &cbRead, NULL))
{
if (cbRead == 0)
{
break;
}
CheckError(bResult, L"ReadFile............................ ");

bResult = CryptHashData(
hHash,
rgbFile,
cbRead,
0
);
CheckError(bResult, L"CryptHashData....................... ");
}
CheckError(bResult, L"ReadFile............................ ");

// Open the file with the signature
hSignatureFile = CreateFileW(
SignatureFileName,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN,
NULL
);
CheckError((hSignatureFile != INVALID_HANDLE_VALUE), L"CreateFile.......................... ");

// Read the signature from the file
pbBinary = (BYTE *)malloc(BUFSIZE);
CheckError((BOOL)pbBinary, L"malloc.............................. ");

bResult = ReadFile(hSignatureFile, pbBinary, BUFSIZE, &cbBinary, NULL);
CheckError(bResult, L"ReadFile............................ ");

// Get the public key from the certificate
CryptImportPublicKeyInfo(
hCryptProv,
MY_TYPE,
&pSignerCert->pCertInfo->SubjectPublicKeyInfo,
&hPubKey
);
CheckError(bResult, L"CryptImportPublicKeyInfo............ ");

// Verify the signature
bResult = CryptVerifySignature(
hHash,
pbBinary,
cbBinary,
hPubKey,
NULL,
0
);
CheckError(bResult, L"CryptVerifySignature................ ");

// Clean up and free memory.
free(pbBinary);

CloseHandle(hDataFile);
CloseHandle(hSignatureFile);

bResult = CryptDestroyHash(hHash);
CheckError(bResult, L"CryptDestroyHash.................... ");

bResult = CertFreeCertificateContext(pSignerCert);
CheckError(bResult, L"CertFreeCertificateContext.......... ");

bResult = CertCloseStore(
hStoreHandle,
CERT_CLOSE_STORE_CHECK_FLAG
);
CheckError(bResult, L"CertCloseStore...................... ");

bResult = CryptReleaseContext(
hCryptProv,
0
);
CheckError(bResult, L"CryptReleaseContext................. ");
}
// End of Verify


</SAMPLE>



I hope this helps.


Cheers,



Alex (Alejandro Campos Magencio)