Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Hi all, welcome back,
Today we'll do some more P/Invoke with CryptoAPI and C# . The following sample is a conversion to C# of the C++ sample in Example C Program: Signing a Message and Verifying a Message Signature:
<SAMPLE file="Class1.cs">
using System;
using System.Text;
using System.ComponentModel;
using System.Runtime.InteropServices;
namespace ConsoleApplication1
{
class Class1
{
[STAThread]
static void Main(string[] args)
{
// Parameters.
//
String sSignerName = "ALEJANDRO CAMPOS MAGENCIO";
String sMessage = "CryptoAPI is a good way to handle security";
// Variables.
//
Byte[] pbMessage = null;
Int32 cbMessage = 0;
IntPtr[] MessageArray = null;
Int32[] MessageSizeArray = null;
IntPtr hStoreHandle = IntPtr.Zero;
IntPtr pSignerCert = IntPtr.Zero;
Crypto.CRYPT_SIGN_MESSAGE_PARA SigParams;
Boolean res = false;
Int32 cbSignedMessageBlob = 0;
Byte[] pbSignedMessageBlob = null;
Crypto.CRYPT_VERIFY_MESSAGE_PARA VerifyParams;
Int32 cbDecodedMessageBlob = 0;
Byte[] pbDecodedMessageBlob = null;
try
{
// Begin processing. Display the original message.
//
Console.WriteLine("-------------------------------------");
Console.WriteLine("MESSAGE TO SIGN:\n");
Console.WriteLine(sMessage + "\n\n");
// Size of message.
//
pbMessage = (new UnicodeEncoding()).GetBytes(sMessage);
cbMessage = pbMessage.Length;
// Create the MessageArray and the MessageSizeArray.
//
MessageArray = new IntPtr[1];
MessageArray[0] = Marshal.AllocHGlobal(pbMessage.Length);
Marshal.Copy(pbMessage, 0, MessageArray[0], pbMessage.Length);
MessageSizeArray = new Int32[1];
MessageSizeArray[0] = cbMessage;
// Open a certificate store.
//
hStoreHandle = Crypto.CertOpenStore(
Crypto.CERT_STORE_PROV_SYSTEM,
0,
IntPtr.Zero,
Crypto.CERT_SYSTEM_STORE_CURRENT_USER,
Crypto.CERT_PERSONAL_STORE_NAME
);
if (hStoreHandle == IntPtr.Zero)
{
throw new Exception("CertOpenStore error", new Win32Exception(Marshal.GetLastWin32Error()));
}
// Get a pointer to the signer's certificate.
// This certificate must have access to the signer's private key.
pSignerCert = Crypto.CertFindCertificateInStore(
hStoreHandle,
Crypto.MY_TYPE,
0,
Crypto.CERT_FIND_SUBJECT_STR,
sSignerName,
IntPtr.Zero
);
if (pSignerCert == IntPtr.Zero)
{
throw new Exception("CertFindCertificateInStore error", new Win32Exception(Marshal.GetLastWin32Error()));
}
// Initialize the signature structure.
//
SigParams = new Crypto.CRYPT_SIGN_MESSAGE_PARA();
SigParams.cbSize = Marshal.SizeOf(SigParams);
SigParams.dwMsgEncodingType = Crypto.MY_TYPE;
SigParams.pSigningCert = pSignerCert;
SigParams.HashAlgorithm.pszObjId = Crypto.szOID_OIWSEC_sha1;
SigParams.HashAlgorithm.Parameters.pbData = IntPtr.Zero;
SigParams.HashAlgorithm.Parameters.cbData = 0;
SigParams.pvHashAuxInfo = IntPtr.Zero;
SigParams.cMsgCert = 1;
GCHandle GC = GCHandle.Alloc(pSignerCert, GCHandleType.Pinned);
SigParams.rgpMsgCert = GC.AddrOfPinnedObject();
GC.Free();
SigParams.cMsgCrl = 0;
SigParams.rgpMsgCrl = IntPtr.Zero;
SigParams.cAuthAttr = 0;
SigParams.rgAuthAttr = IntPtr.Zero;
SigParams.cUnauthAttr = 0;
SigParams.rgUnauthAttr = IntPtr.Zero;
SigParams.dwFlags = 0;
SigParams.dwInnerContentType = 0;
// With two calls to CryptSignMessage, sign the message.
// First, get the size of the output signed BLOB.
//
res = Crypto.CryptSignMessage(
ref SigParams, // Signature parameters
false, // Not detached
1, // Number of messages
MessageArray, // Messages to be signed
MessageSizeArray, // Size of messages
null, // Buffer for signed message
ref cbSignedMessageBlob // Size of buffer
);
if (res == false)
{
throw new Exception("CryptSignMessage error", new Win32Exception(Marshal.GetLastWin32Error()));
}
// Allocate memory for the signed BLOB.
//
pbSignedMessageBlob = new Byte[cbSignedMessageBlob];
// Get the SignedMessageBlob.
//
res = Crypto.CryptSignMessage(
ref SigParams, // Signature parameters
false, // Not detached
1, // Number of messages
MessageArray, // Messages to be signed
MessageSizeArray, // Size of messages
pbSignedMessageBlob, // Buffer for signed message
ref cbSignedMessageBlob // Size of buffer
);
if (res == false)
{
throw new Exception("CryptSignMessage error", new Win32Exception(Marshal.GetLastWin32Error()));
}
// pbSignedMessageBlob points to the signed BLOB. Display the signature.
//
Console.WriteLine("-------------------------------------");
Console.WriteLine("SIGNATURE:\n");
Console.WriteLine(Convert.ToBase64String(pbSignedMessageBlob) + "\n\n");
// Verify the message signature. Usually, this
// would be done in a separate program.
//
// Initialize the VerifyParams data structure.
//
VerifyParams = new Crypto.CRYPT_VERIFY_MESSAGE_PARA();
VerifyParams.cbSize = Marshal.SizeOf(VerifyParams);
VerifyParams.dwMsgAndCertEncodingType = Crypto.MY_TYPE;
VerifyParams.hCryptProv = IntPtr.Zero;
VerifyParams.pfnGetSignerCertificate = IntPtr.Zero;
VerifyParams.pvGetArg = IntPtr.Zero;
// With two calls to CryptVerifyMessageSignature, verify and decode
// the signed message.
// First, call CryptVerifyMessageSignature to get the length of the
// buffer needed to hold the decoded message.
//
res = Crypto.CryptVerifyMessageSignature(
ref VerifyParams, // Verify parameters.
0, // Signer index.
pbSignedMessageBlob, // Pointer to signed BLOB.
cbSignedMessageBlob, // Size of signed BLOB.
null, // Buffer for decoded message.
ref cbDecodedMessageBlob, // Size of buffer.
IntPtr.Zero // Pointer to signer certificate.
);
if (res == false)
{
throw new Exception("CryptVerifyMessageSignature error", new Win32Exception(Marshal.GetLastWin32Error()));
}
// Allocate memory for the buffer.
//
pbDecodedMessageBlob = new Byte[cbDecodedMessageBlob];
// Call CryptVerifyMessageSignature again to copy the message into
// the buffer.
//
res = Crypto.CryptVerifyMessageSignature(
ref VerifyParams, // Verify parameters.
0, // Signer index.
pbSignedMessageBlob, // Pointer to signed BLOB.
cbSignedMessageBlob, // Size of signed BLOB.
pbDecodedMessageBlob, // Buffer for decoded message.
ref cbDecodedMessageBlob, // Size of buffer.
IntPtr.Zero // Pointer to signer certificate.
);
if (res == false)
{
throw new Exception("CryptVerifyMessageSignature error", new Win32Exception(Marshal.GetLastWin32Error()));
}
else
{
// Display attached message to signature.
//
Console.WriteLine("-------------------------------------");
Console.WriteLine("SIGNATURE VERIFIED!!!\n\n");
Console.WriteLine("-------------------------------------");
Console.WriteLine("ATTACHED MESSAGE:\n");
Console.WriteLine((new UnicodeEncoding()).GetString(pbDecodedMessageBlob) + "\n\n");
}
}
catch (Exception ex)
{
// Any errors? Show them.
//
if (ex.InnerException == null)
{
Console.WriteLine(ex.Message + "\n\n");
}
else
{
Console.WriteLine(ex.Message + " --> " + ex.InnerException.Message + "\n\n");
}
}
finally
{
// Clean up and free memory.
//
if (MessageArray[0] != IntPtr.Zero)
{
Marshal.FreeHGlobal(MessageArray[0]);
}
if (pSignerCert != IntPtr.Zero)
{
Crypto.CertFreeCertificateContext(pSignerCert);
}
if (hStoreHandle != IntPtr.Zero)
{
Crypto.CertCloseStore(
hStoreHandle,
Crypto.CERT_CLOSE_STORE_CHECK_FLAG
);
}
}
Console.WriteLine("<<Press ENTER to continue>>" + "\n");
Console.ReadLine();
}
}
}
</SAMPLE>
<SAMPLE file="Crypto.cs">
using System;
using System.Runtime.InteropServices;
public class Crypto
{
#region CONSTS
// #define CERT_PERSONAL_STORE_NAME L"My"
public const string CERT_PERSONAL_STORE_NAME = "My";
// #define CERT_COMPARE_NAME 2
public const Int32 CERT_COMPARE_NAME = 2;
// #define CERT_INFO_SUBJECT_FLAG 7
public const Int32 CERT_INFO_SUBJECT_FLAG = 7;
// #define CERT_COMPARE_SHIFT 16
public const Int32 CERT_COMPARE_SHIFT = 16;
// #define CERT_FIND_SUBJECT_NAME (CERT_COMPARE_NAME << CERT_COMPARE_SHIFT | CERT_INFO_SUBJECT_FLAG)
public const Int32 CERT_FIND_SUBJECT_NAME =
(CERT_COMPARE_NAME << CERT_COMPARE_SHIFT) | CERT_INFO_SUBJECT_FLAG;
// #define CERT_COMPARE_NAME_STR_W 8
public const Int32 CERT_COMPARE_NAME_STR_W = 8;
// #define CERT_FIND_SUBJECT_STR_W // (CERT_COMPARE_NAME_STR_W << CERT_COMPARE_SHIFT | CERT_INFO_SUBJECT_FLAG)
public const Int32 CERT_FIND_SUBJECT_STR_W =
(CERT_COMPARE_NAME_STR_W << CERT_COMPARE_SHIFT) | CERT_INFO_SUBJECT_FLAG;
// #define CERT_FIND_SUBJECT_STR CERT_FIND_SUBJECT_STR_W
public const Int32 CERT_FIND_SUBJECT_STR = CERT_FIND_SUBJECT_STR_W;
// #define CERT_STORE_PROV_SYSTEM_W ((LPCSTR) 10)
public const Int32 CERT_STORE_PROV_SYSTEM_W = 10;
// #define CERT_STORE_PROV_SYSTEM CERT_STORE_PROV_SYSTEM_W
public const Int32 CERT_STORE_PROV_SYSTEM = CERT_STORE_PROV_SYSTEM_W;
// #define CERT_SYSTEM_STORE_CURRENT_USER_ID 1
public const Int32 CERT_SYSTEM_STORE_CURRENT_USER_ID = 1;
// #define CERT_SYSTEM_STORE_LOCATION_SHIFT 16
public const Int32 CERT_SYSTEM_STORE_LOCATION_SHIFT = 16;
// #define CERT_SYSTEM_STORE_CURRENT_USER // (CERT_SYSTEM_STORE_CURRENT_USER_ID << CERT_SYSTEM_STORE_LOCATION_SHIFT)
public const Int32 CERT_SYSTEM_STORE_CURRENT_USER =
CERT_SYSTEM_STORE_CURRENT_USER_ID << CERT_SYSTEM_STORE_LOCATION_SHIFT;
// #define CERT_CLOSE_STORE_CHECK_FLAG 0x00000002
public const Int32 CERT_CLOSE_STORE_CHECK_FLAG = 0x00000002;
// #define ALG_CLASS_HASH (4 << 13)
// #define ALG_TYPE_ANY (0)
// #define ALG_SID_SHA1 4
// #define CALG_SHA1 (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA1)
public const Int32 CALG_SHA1 = (4 << 13) | 4;
// #define ALG_CLASS_SIGNATURE (1 << 13)
// #define ALG_TYPE_RSA (2 << 9)
// #define ALG_SID_RSA_ANY 0
// #define CALG_RSA_SIGN (ALG_CLASS_SIGNATURE | ALG_TYPE_RSA | ALG_SID_RSA_ANY)
public const Int32 CALG_RSA_SIGN = (1 << 13) | (2 << 9);
// #define PROV_RSA_FULL 1
public const Int32 PROV_RSA_FULL = 0x00000001;
// #define CRYPT_VERIFYCONTEXT 0xF0000000
public const UInt32 CRYPT_VERIFYCONTEXT = 0xF0000000; //No private key access required
// #define X509_ASN_ENCODING 0x00000001
public const Int32 X509_ASN_ENCODING = 0x00000001;
// #define PKCS_7_ASN_ENCODING 0x00010000
public const Int32 PKCS_7_ASN_ENCODING = 0x00010000;
// #define MY_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
public const Int32 MY_TYPE = PKCS_7_ASN_ENCODING | X509_ASN_ENCODING;
// #define HP_HASHVAL 0x0002
public const Int32 HP_HASHVAL = 0x00000002;
// #define HP_HASHSIZE 0x0004
public const Int32 HP_HASHSIZE = 0x00000004;
// #define PUBLICKEYBLOBEX 0xA
public const Int32 PUBLICKEYBLOBEX = 0x0A;
// #define PUBLICKEYBLOB 0x6
public const Int32 PUBLICKEYBLOB = 0x06;
// #define CUR_BLOB_VERSION 0x02
public const Int32 CUR_BLOB_VERSION = 0x02;
// #define CRYPT_EXPORTABLE 0x00000001
public const Int32 CRYPT_EXPORTABLE = 0x00000001;
// #define szOID_RSA_MD5 "1.2.840.113549.2.5"
public const String szOID_RSA_MD5 = "1.2.840.113549.2.5";
// #define szOID_RSA_MD5RSA "1.2.840.113549.1.1.4"
public const String szOID_RSA_MD5RSA = "1.2.840.113549.1.1.4";
// #define szOID_OIWSEC_sha1 "1.3.14.3.2.26"
public const String szOID_OIWSEC_sha1 = "1.3.14.3.2.26";
#endregion
#region STRUCTS
// typedef struct _PUBLICKEYSTRUC
// {
// BYTE bType;
// BYTE bVersion;
// WORD reserved;
// ALG_ID aiKeyAlg;
// } BLOBHEADER, PUBLICKEYSTRUC;
[StructLayout(LayoutKind.Sequential)]
public struct PUBLICKEYSTRUC
{
public Byte bType;
public Byte bVersion;
public Int16 reserved;
public Int32 aiKeyAlg;
}
// typedef struct _RSAPUBKEY
// {
// DWORD magic;
// DWORD bitlen;
// DWORD pubexp;
// } RSAPUBKEY;
[StructLayout(LayoutKind.Sequential)]
public struct RSAPUBKEY
{
public Int32 magic;
public Int32 bitlen;
public Int32 pubexp;
}
// typedef struct _CRYPTOAPI_BLOB
// {
// DWORD cbData;
// BYTE *pbData;
// } CRYPT_HASH_BLOB, CRYPT_INTEGER_BLOB,
// CRYPT_OBJID_BLOB, CERT_NAME_BLOB;
[StructLayout(LayoutKind.Sequential)]
public struct CRYPTOAPI_BLOB
{
public Int32 cbData;
public IntPtr pbData;
}
// typedef struct _CRYPT_ALGORITHM_IDENTIFIER
// {
// LPSTR pszObjId;
// CRYPT_OBJID_BLOB Parameters;
// } CRYPT_ALGORITHM_IDENTIFIER;
[StructLayout(LayoutKind.Sequential)]
public struct CRYPT_ALGORITHM_IDENTIFIER
{
[MarshalAs(UnmanagedType.LPStr)]public String pszObjId;
public CRYPTOAPI_BLOB Parameters;
}
// typedef struct _CRYPT_SIGN_MESSAGE_PARA
// {
// DWORD cbSize;
// DWORD dwMsgEncodingType;
// PCCERT_CONTEXT pSigningCert;
// CRYPT_ALGORITHM_IDENTIFIER HashAlgorithm;
// void *pvHashAuxInfo;
// DWORD cMsgCert;
// PCCERT_CONTEXT *rgpMsgCert;
// DWORD cMsgCrl;
// PCCRL_CONTEXT *rgpMsgCrl;
// DWORD cAuthAttr;
// PCRYPT_ATTRIBUTE rgAuthAttr;
// DWORD cUnauthAttr;
// PCRYPT_ATTRIBUTE rgUnauthAttr;
// DWORD dwFlags;
// DWORD dwInnerContentType;
// } CRYPT_SIGN_MESSAGE_PARA;
[StructLayout(LayoutKind.Sequential)]
public struct CRYPT_SIGN_MESSAGE_PARA
{
public Int32 cbSize;
public Int32 dwMsgEncodingType;
public IntPtr pSigningCert;
public CRYPT_ALGORITHM_IDENTIFIER HashAlgorithm;
public IntPtr pvHashAuxInfo;
public Int32 cMsgCert;
public IntPtr rgpMsgCert;
public Int32 cMsgCrl;
public IntPtr rgpMsgCrl;
public Int32 cAuthAttr;
public IntPtr rgAuthAttr;
public Int32 cUnauthAttr;
public IntPtr rgUnauthAttr;
public Int32 dwFlags;
public Int32 dwInnerContentType;
}
// typedef struct _CRYPT_VERIFY_MESSAGE_PARA
// {
// DWORD cbSize;
// DWORD dwMsgAndCertEncodingType;
// HCRYPTPROV hCryptProv;
// PFN_CRYPT_GET_SIGNER_CERTIFICATE pfnGetSignerCertificate;
// void *pvGetArg;
// } CRYPT_VERIFY_MESSAGE_PARA;
[StructLayout(LayoutKind.Sequential)]
public struct CRYPT_VERIFY_MESSAGE_PARA
{
public Int32 cbSize;
public Int32 dwMsgAndCertEncodingType;
public IntPtr hCryptProv;
public IntPtr pfnGetSignerCertificate;
public IntPtr pvGetArg;
}
#endregion
#region FUNCTIONS (IMPORTS)
// HCERTSTORE WINAPI CertOpenStore(
// LPCSTR lpszStoreProvider,
// DWORD dwMsgAndCertEncodingType,
// HCRYPTPROV hCryptProv,
// DWORD dwFlags,
// const void* pvPara
// );
[DllImport("Crypt32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern IntPtr CertOpenStore(
Int32 lpszStoreProvider,
Int32 dwMsgAndCertEncodingType,
IntPtr hCryptProv,
Int32 dwFlags,
String pvPara
);
// HCERTSTORE WINAPI CertOpenSystemStore(
// HCRYPTPROV hprov,
// LPTCSTR szSubsystemProtocol
// );
[DllImport("Crypt32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern IntPtr CertOpenSystemStore(
IntPtr hprov,
String szSubsystemProtocol
);
// BOOL WINAPI CertCloseStore(
// HCERTSTORE hCertStore,
// DWORD dwFlags
// );
[DllImport("Crypt32.dll", SetLastError=true)]
public static extern Boolean CertCloseStore(
IntPtr hCertStore,
Int32 dwFlags
);
// BOOL WINAPI CryptAcquireContext(
// HCRYPTPROV* phProv,
// LPCTSTR pszContainer,
// LPCTSTR pszProvider,
// DWORD dwProvType,
// DWORD dwFlags
// );
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern bool CryptAcquireContext(
ref IntPtr hProv,
String pszContainer,
String pszProvider,
Int32 dwProvType,
Int32 dwFlags
);
// BOOL WINAPI CryptCreateHash(
// HCRYPTPROV hProv,
// ALG_ID Algid,
// HCRYPTKEY hKey,
// DWORD dwFlags,
// HCRYPTHASH* phHash
// );
[DllImport("advapi32.dll", SetLastError=true)]
public static extern bool CryptCreateHash(
IntPtr hProv,
Int32 Algid,
IntPtr hKey,
Int32 dwFlags,
ref IntPtr phHash
);
// BOOL WINAPI CryptGetHashParam(
// HCRYPTHASH hHash,
// DWORD dwParam,
// BYTE* pbData,
// DWORD* pdwDataLen,
// DWORD dwFlags
// );
[DllImport("advapi32.dll", SetLastError=true)]
public static extern bool CryptGetHashParam(
IntPtr hHash,
Int32 dwParam,
ref Int32 pbData,
ref Int32 pdwDataLen,
Int32 dwFlags
);
// BOOL WINAPI CryptSetHashParam(
// HCRYPTHASH hHash,
// DWORD dwParam,
// BYTE* pbData,
// DWORD dwFlags
// );
[DllImport("advapi32.dll", SetLastError=true)]
public static extern bool CryptSetHashParam(
IntPtr hHash,
Int32 dwParam,
Byte[] pbData,
Int32 dwFlags
);
// BOOL WINAPI CryptImportPublicKeyInfo(
// HCRYPTPROV hCryptProv,
// DWORD dwCertEncodingType,
// PCERT_PUBLIC_KEY_INFO pInfo,
// HCRYPTKEY* phKey
// );
[DllImport("crypt32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern bool CryptImportPublicKeyInfo(
IntPtr hCryptProv,
Int32 dwCertEncodingType,
IntPtr pInfo,
ref IntPtr phKey
);
// BOOL WINAPI CryptImportKey(
// HCRYPTPROV hProv,
// BYTE* pbData,
// DWORD dwDataLen,
// HCRYPTKEY hPubKey,
// DWORD dwFlags,
// HCRYPTKEY* phKey
// );
[DllImport("advapi32.dll", SetLastError=true)]
public static extern bool CryptImportKey(
IntPtr hProv,
Byte[] pbData,
Int32 dwDataLen,
IntPtr hPubKey,
Int32 dwFlags,
ref IntPtr phKey
);
// BOOL WINAPI CryptVerifySignature(
// HCRYPTHASH hHash,
// BYTE* pbSignature,
// DWORD dwSigLen,
// HCRYPTKEY hPubKey,
// LPCTSTR sDescription,
// DWORD dwFlags
// );
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern bool CryptVerifySignature(
IntPtr hHash,
Byte[] pbSignature,
Int32 dwSigLen,
IntPtr hPubKey,
String sDescription,
Int32 dwFlags
);
// BOOL WINAPI CryptDestroyKey(
// HCRYPTKEY hKey
// );
[DllImport("advapi32.dll", SetLastError=true)]
public static extern bool CryptDestroyKey(
IntPtr hKey
);
// BOOL WINAPI CryptDestroyHash(
// HCRYPTHASH hHash
// );
[DllImport("advapi32.dll", SetLastError=true)]
public static extern bool CryptDestroyHash(
IntPtr hHash
);
// BOOL WINAPI CryptReleaseContext(
// HCRYPTPROV hProv,
// DWORD dwFlags
// );
[DllImport("advapi32.dll", SetLastError=true)]
public static extern bool CryptReleaseContext(
IntPtr hProv,
Int32 dwFlags
);
// BOOL WINAPI CryptGenKey(
// HCRYPTPROV hProv,
// ALG_ID Algid,
// DWORD dwFlags,
// HCRYPTKEY* phKey
// );
[DllImport("advapi32.dll", SetLastError=true)]
public static extern bool CryptGenKey(
IntPtr hProv,
Int32 Algid,
Int32 dwFlags,
ref IntPtr phKey
);
// BOOL WINAPI CryptExportKey(
// HCRYPTKEY hKey,
// HCRYPTKEY hExpKey,
// DWORD dwBlobType,
// DWORD dwFlags,
// BYTE* pbData,
// DWORD* pdwDataLen
// );
[DllImport("advapi32.dll", SetLastError=true)]
public static extern bool CryptExportKey(
IntPtr hKey,
IntPtr hExpKey,
Int32 dwBlobType,
Int32 dwFlags,
Byte[] pbData,
ref Int32 pdwDataLen
);
// PCCERT_CONTEXT WINAPI CertFindCertificateInStore(
// HCERTSTORE hCertStore,
// DWORD dwCertEncodingType,
// DWORD dwFindFlags,
// DWORD dwFindType,
// const void* pvFindPara,
// PCCERT_CONTEXT pPrevCertContext
// );
[DllImport("Crypt32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern IntPtr CertFindCertificateInStore(
IntPtr hCertStore,
Int32 dwCertEncodingType,
Int32 dwFindFlags,
Int32 dwFindType,
String pvFindPara,
IntPtr pPrevCertContext
);
// BOOL WINAPI CertFreeCertificateContext(
// PCCERT_CONTEXT pCertContext
// );
[DllImport("Crypt32.dll", SetLastError=true)]
public static extern Boolean CertFreeCertificateContext(
IntPtr pCertContext
);
// BOOL WINAPI CryptSignMessage(
// PCRYPT_SIGN_MESSAGE_PARA pSignPara,
// BOOL fDetachedSignature,
// DWORD cToBeSigned,
// const BYTE* rgpbToBeSigned[],
// DWORD rgcbToBeSigned[],
// BYTE* pbSignedBlob,
// DWORD* pcbSignedBlob
// );
[DllImport("Crypt32.dll", SetLastError=true)]
public static extern Boolean CryptSignMessage (
ref CRYPT_SIGN_MESSAGE_PARA pSignPara,
Boolean fDetachedSignature,
Int32 cToBeSigned,
IntPtr[] rgpbToBeSigned,
Int32[] rgcbToBeSigned,
Byte[] pbSignedBlob,
ref Int32 pcbSignedBlob
);
// BOOL WINAPI CryptVerifyMessageSignature(
// PCRYPT_VERIFY_MESSAGE_PARA pVerifyPara,
// DWORD dwSignerIndex,
// const BYTE* pbSignedBlob,
// DWORD cbSignedBlob,
// BYTE* pbDecoded,
// DWORD* pcbDecoded,
// PCCERT_CONTEXT* ppSignerCert
// );
[DllImport("Crypt32.dll", SetLastError=true)]
public static extern Boolean CryptVerifyMessageSignature (
ref CRYPT_VERIFY_MESSAGE_PARA pVerifyPara,
Int32 dwSignerIndex,
Byte[] pbSignedBlob,
Int32 cbSignedBlob,
Byte[] pbDecoded,
ref Int32 pcbDecoded,
IntPtr ppSignerCert
);
#endregion
#region FUNTIONS
// Helper function to convert struts & classes to byte array
public static byte[] RawSerialize(object anything)
{
int rawsize = Marshal.SizeOf(anything);
IntPtr buffer = Marshal.AllocHGlobal(rawsize);
Marshal.StructureToPtr(anything, buffer, false);
byte[] rawdatas = new byte[rawsize];
Marshal.Copy(buffer, rawdatas, 0, rawsize);
Marshal.FreeHGlobal(buffer);
return rawdatas;
}
#endregion
}
</SAMPLE>
Note: I know there are easier ways now in .NET to handle certificate stores (X509Store) and certificates (X509Certificate2), but I decided to include the P/Invoke declarations in case you need them and for illustration purposes.
I hope this helps.
Cheers,
Alex (Alejandro Campos Magencio)
Comments
- Anonymous
November 23, 2008
Hi Alex,Your example has been good so far for me. I am able to successfully produce a PKCS7 message from the code you have posted.Now, next is that I want to add authenticated attribute to this PKCS7 message. Unfortunately, I found that you have not discussed it in the example. I have written some code to achieve it myself but I am getting access violation on CryptSignMessage API.I think I am not correctly marshaling the data. Can you help me point it out?Here is the code which I have written to add authenticated attribute.//------------------------------------------------------- // Specify authenticated attributes. SigParams.cAuthAttr = (uint)_signed_attributes.Count; SigParams.rgAuthAttr = Marshal.AllocHGlobal(_signed_attributes.Count * Marshal.SizeOf(typeof(NativeWrapper.CRYPT_ATTRIBUTE))); int j = 0; foreach (KeyValuePair<string, byte[]> att in _signed_attributes) { // Prepare Blob from ByteArray. NativeWrapper.CRYPTOAPI_BLOB blob = new NativeWrapper.CRYPTOAPI_BLOB(); blob.cbData = (uint)att.Value.Length; blob.pbData = Marshal.AllocHGlobal(att.Value.Length); Marshal.Copy(att.Value, 0, blob.pbData, att.Value.Length); // Prepare CRYPT_ATTRIBUTE structure. NativeWrapper.CRYPT_ATTRIBUTE authatt = new NativeWrapper.CRYPT_ATTRIBUTE(); authatt.pszObjId = "1.2.840.113583.1.1.8"; authatt.cValue = 1; authatt.rgValue = Marshal.AllocHGlobal(authatt.cValue * Marshal.SizeOf(typeof(NativeWrapper.CRYPTOAPI_BLOB))); Marshal.StructureToPtr(blob, authatt.rgValue, false); // Marshal CRYPT_ATTRIBUTE structure to the SigParams.rgAuthAttr array. IntPtr pauthatt = new IntPtr(SigParams.rgAuthAttr.ToInt32() + j * Marshal.SizeOf(typeof (NativeWrapper.CRYPT_ATTRIBUTE))); Marshal.StructureToPtr(authatt, pauthatt, false); ++j; } //-------------------------------------------------------Thanks and Regards