Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Hi all,
Some time ago I posted the following sample How to call CryptMsg API in streaming mode (C#).Well, I continued working on that CryptMsg sample, and I got many consts, structs and API declarations that may help you if you need to p/invoke CryptoAPI in C# . You may also want to check this other post of mine: P/Invoking CryptoAPI in .NET (C# version), to see more CryptoAPI declarations.
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Security.Cryptography.X509Certificates;
using System.ComponentModel;
using System.Security.Cryptography;
namespace LargeCMS
{
partial class Win32
{
#region "CONSTS"
internal const int X509_ASN_ENCODING = 0x00000001;
internal const int PKCS_7_ASN_ENCODING = 0x00010000;
internal const int CMSG_SIGNED = 2;
internal const int CMSG_ENVELOPED = 3;
internal const int CMSG_DETACHED_FLAG = 0x00000004;
internal const int CMSG_AUTHENTICATED_ATTRIBUTES_FLAG = 0x00000008;
internal const int CMSG_ENVELOPE_ALGORITHM_PARAM = 15;
internal const int CMSG_ENCODED_SIGNER = 8;
internal const int CMSG_ENCODED_MESSAGE = 29;
internal const int CMSG_CTRL_VERIFY_SIGNATURE = 1;
internal const int CMSG_CTRL_DECRYPT = 2;
internal const int CMSG_CTRL_VERIFY_SIGNATURE_EX = 19;
internal const int CMSG_CTRL_ADD_SIGNER = 6;
internal const int CMSG_CTRL_ADD_CERT = 10;
internal const int CMSG_SIGNER_COUNT_PARAM = 5;
internal const int CMSG_SIGNER_INFO_PARAM = 6;
internal const int CMSG_SIGNER_CERT_INFO_PARAM = 7;
internal const int CMSG_CERT_COUNT_PARAM = 11;
internal const int CMSG_CERT_PARAM = 12;
internal const int CMSG_RECIPIENT_COUNT_PARAM = 17;
internal const int CMSG_RECIPIENT_INFO_PARAM = 19;
internal const int CMSG_VERIFY_SIGNER_CERT = 2;
internal const int CMSG_RC4_NO_SALT_FLAG = 0x40000000;
internal const int AT_KEYEXCHANGE = 1;
internal const int AT_SIGNATURE = 2;
internal const String szOID_OIWSEC_rsaSign = "1.3.14.3.2.11";
internal const String szOID_OIWSEC_shaRSA = "1.3.14.3.2.15";
internal const String szOID_OIWSEC_sha = "1.3.14.3.2.18";
internal const String szOID_OIWSEC_sha1 = "1.3.14.3.2.26";
internal const String szOID_OIWSEC_sha1RSASign = "1.3.14.3.2.29";
internal const String szOID_RSA_RC4 = "1.2.840.113549.3.4";
internal const String szOID_RSA_DES_EDE3_CBC = "1.2.840.113549.3.7";
internal const String szOID_RSA_signingTime = "1.2.840.113549.1.9.5";
internal const int X509_NAME = 7;
internal const int CERT_STORE_PROV_MSG = 1;
internal const int CERT_CLOSE_STORE_FORCE_FLAG = 1;
internal const int CERT_KEY_PROV_INFO_PROP_ID = 2;
internal const int CERT_STORE_PROV_SYSTEM = 10;
internal const int CERT_SYSTEM_STORE_CURRENT_USER = 1 << 16;
#endregion
#region "STRUCTS"
[StructLayout(LayoutKind.Sequential)]
internal struct CRYPT_ALGORITHM_IDENTIFIER
{
public string pszObjId;
public BLOB Parameters;
public void Dispose()
{
Parameters.Dispose();
}
}
[StructLayout(LayoutKind.Sequential)]
internal struct CERT_ID
{
public int dwIdChoice;
public BLOB IssuerSerialNumberOrKeyIdOrHashId;
}
[StructLayout(LayoutKind.Sequential)]
internal struct CRYPT_ATTRIBUTE
{
public string pszObjId;
public int cValue;
public IntPtr rgValue;
public void Dispose()
{
if (!rgValue.Equals(IntPtr.Zero)) { Marshal.FreeHGlobal(rgValue); }
}
}
[StructLayout(LayoutKind.Sequential)]
internal struct CMSG_SIGNER_ENCODE_INFO
{
public int cbSize;
public IntPtr pCertInfo;
public IntPtr hCryptProvOrhNCryptKey;
public int dwKeySpec;
public CRYPT_ALGORITHM_IDENTIFIER HashAlgorithm;
public IntPtr pvHashAuxInfo;
public int cAuthAttr;
public IntPtr rgAuthAttr;
public int cUnauthAttr;
public IntPtr rgUnauthAttr;
public CERT_ID SignerId;
public CRYPT_ALGORITHM_IDENTIFIER HashEncryptionAlgorithm;
public IntPtr pvHashEncryptionAuxInfo;
public void Dispose()
{
if (!hCryptProvOrhNCryptKey.Equals(IntPtr.Zero)) { Win32.CryptReleaseContext(hCryptProvOrhNCryptKey, 0); }
if (!rgAuthAttr.Equals(IntPtr.Zero)) { Marshal.FreeHGlobal(rgAuthAttr); }
if (!rgUnauthAttr.Equals(IntPtr.Zero)) { Marshal.FreeHGlobal(rgUnauthAttr); }
}
}
[StructLayout(LayoutKind.Sequential)]
internal struct CERT_CONTEXT
{
public int dwCertEncodingType;
public IntPtr pbCertEncoded;
public int cbCertEncoded;
public IntPtr pCertInfo;
public IntPtr hCertStore;
}
[StructLayout(LayoutKind.Sequential)]
internal struct BLOB
{
public int cbData;
public IntPtr pbData;
public void Dispose()
{
if (!pbData.Equals(IntPtr.Zero)) { Marshal.FreeHGlobal(pbData); }
}
}
[StructLayout(LayoutKind.Sequential)]
internal struct CRYPT_BIT_BLOB
{
public int cbData;
public IntPtr pbData;
public int cUnusedBits;
}
[StructLayout(LayoutKind.Sequential)]
internal struct CMSG_SIGNED_ENCODE_INFO
{
public int cbSize;
public int cSigners;
public IntPtr rgSigners;
public int cCertEncoded;
public IntPtr rgCertEncoded;
public int cCrlEncoded;
public IntPtr rgCrlEncoded;
public int cAttrCertEncoded;
public IntPtr rgAttrCertEncoded;
public void Dispose()
{
if (!rgSigners.Equals(IntPtr.Zero)) { Marshal.FreeHGlobal(rgSigners); }
if (!rgCertEncoded.Equals(IntPtr.Zero)) { Marshal.FreeHGlobal(rgCertEncoded); }
if (!rgCrlEncoded.Equals(IntPtr.Zero)) { Marshal.FreeHGlobal(rgCrlEncoded); }
if (!rgAttrCertEncoded.Equals(IntPtr.Zero)) { Marshal.FreeHGlobal(rgAttrCertEncoded); }
}
}
[StructLayout(LayoutKind.Sequential)]
internal struct CRYPT_ATTRIBUTES
{
public int cAttr;
public IntPtr rgAttr;
}
[StructLayout(LayoutKind.Sequential)]
internal struct CMSG_SIGNER_INFO
{
public int dwVersion;
public BLOB Issuer;
public BLOB SerialNumber;
public CRYPT_ALGORITHM_IDENTIFIER HashAlgorithm;
public CRYPT_ALGORITHM_IDENTIFIER HashEncryptionAlgorithm;
public BLOB EncryptedHash;
public CRYPT_ATTRIBUTES AuthAttrs;
public CRYPT_ATTRIBUTES UnauthAttrs;
}
[StructLayout(LayoutKind.Sequential)]
internal struct CMSG_STREAM_INFO
{
public int cbContent;
public StreamOutputCallbackDelegate pfnStreamOutput;
public IntPtr pvArg;
}
[StructLayout(LayoutKind.Sequential)]
internal struct CERT_PUBLIC_KEY_INFO
{
public CRYPT_ALGORITHM_IDENTIFIER Algorithm;
public CRYPT_BIT_BLOB PublicKey;
}
[StructLayout(LayoutKind.Sequential)]
internal struct FILETIME
{
public int dwLowDateTime;
public int dwHighDateTime;
}
[StructLayout(LayoutKind.Sequential)]
internal struct CERT_INFO
{
public int dwVersion;
public BLOB SerialNumber;
public CRYPT_ALGORITHM_IDENTIFIER SignatureAlgorithm;
public BLOB Issuer;
public FILETIME NotBefore;
public FILETIME NotAfter;
public BLOB Subject;
public CERT_PUBLIC_KEY_INFO SubjectPublicKeyInfo;
public CRYPT_BIT_BLOB IssuerUniqueId;
public CRYPT_BIT_BLOB SubjectUniqueId;
public int cExtension;
public IntPtr rgExtension;
}
[StructLayout(LayoutKind.Sequential)]
internal struct CMSG_CTRL_VERIFY_SIGNATURE_EX_PARA
{
public int cbSize;
public IntPtr hCryptProv;
public int dwSignerIndex;
public int dwSignerType;
public IntPtr pvSigner;
}
[StructLayout(LayoutKind.Sequential)]
internal struct CMSG_ENVELOPED_ENCODE_INFO
{
public int cbSize;
public IntPtr hCryptProv;
public CRYPT_ALGORITHM_IDENTIFIER ContentEncryptionAlgorithm;
public IntPtr pvEncryptionAuxInfo;
public int cRecipients;
public IntPtr rgpRecipients;
public IntPtr rgCmsRecipients;
public int cCertEncoded;
public IntPtr rgCertEncoded;
public int cCrlEncoded;
public IntPtr rgCrlEncoded;
public int cAttrCertEncoded;
public IntPtr rgAttrCertEncoded;
public int cUnprotectedAttr;
public IntPtr rgUnprotectedAttr;
public void Dispose()
{
ContentEncryptionAlgorithm.Dispose();
if (!pvEncryptionAuxInfo.Equals(IntPtr.Zero)) { Marshal.FreeHGlobal(pvEncryptionAuxInfo); }
if (!rgpRecipients.Equals(IntPtr.Zero)) { Marshal.FreeHGlobal(rgpRecipients); }
}
}
[StructLayout(LayoutKind.Sequential)]
internal struct CMSG_RC4_AUX_INFO
{
public int cbSize;
public int dwBitLen;
}
[StructLayout(LayoutKind.Sequential)]
internal struct CMSG_CTRL_DECRYPT_PARA
{
public int cbSize;
public IntPtr hCryptProvOrNCryptKey;
public int dwKeySpec;
public int dwRecipientIndex;
}
[StructLayout(LayoutKind.Sequential)]
internal struct CRYPT_KEY_PROV_INFO
{
[MarshalAs(UnmanagedType.LPWStr)]public string pwszContainerName;
[MarshalAs(UnmanagedType.LPWStr)]public string pwszProvName;
public int dwProvType;
public int dwFlags;
public int cProvParam;
public IntPtr rgProvParam;
public int dwKeySpec;
}
#endregion
#region "DELEGATES"
internal delegate Boolean StreamOutputCallbackDelegate(IntPtr pvArg, IntPtr pbData, int cbData, Boolean fFinal);
#endregion
#region "API"
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern Boolean CryptAcquireContext(
out SafeCSPHandle hProv,
string pszContainer,
string pszProvider,
int dwProvType,
int dwFlags
);
[DllImport("crypt32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
internal static extern bool CryptEncodeObject(
int dwCertEncodingType,
string lpszStructType,
ref long pvStructInfo,
SafeNTHeapHandle pbEncoded,
ref int pcbEncoded
);
[DllImport("crypt32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
internal static extern Boolean CryptDecodeObject(
int dwCertEncodingType,
string lpszStructType,
IntPtr pbEncoded,
int cbEncoded,
int dwFlags,
out long pvStructInfo,
ref int pcbStructInfo
);
[DllImport("crypt32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
internal static extern Boolean CryptDecodeObject(
int dwCertEncodingType,
int lpszStructType,
IntPtr pbEncoded,
int cbEncoded,
int dwFlags,
StringBuilder pvStructInfo,
ref int pcbStructInfo
);
[DllImport("Crypt32.dll", SetLastError = true)]
internal static extern SafeMsgHandle CryptMsgOpenToEncode(
int dwMsgEncodingType,
int dwFlags,
int dwMsgType,
ref CMSG_SIGNED_ENCODE_INFO pvMsgEncodeInfo,
string pszInnerContentObjID,
ref CMSG_STREAM_INFO pStreamInfo
);
[DllImport("Crypt32.dll", SetLastError = true)]
internal static extern SafeMsgHandle CryptMsgOpenToEncode(
int dwMsgEncodingType,
int dwFlags,
int dwMsgType,
ref CMSG_ENVELOPED_ENCODE_INFO pvMsgEncodeInfo,
string pszInnerContentObjID,
ref CMSG_STREAM_INFO pStreamInfo
);
[DllImport("Crypt32.dll", SetLastError = true)]
internal static extern SafeMsgHandle CryptMsgOpenToDecode(
int dwMsgEncodingType,
int dwFlags,
int dwMsgType,
IntPtr hCryptProv,
IntPtr pRecipientInfo,
ref CMSG_STREAM_INFO pStreamInfo
);
[DllImport("Crypt32.dll", SetLastError = true)]
internal static extern SafeMsgHandle CryptMsgOpenToDecode(
int dwMsgEncodingType,
int dwFlags,
int dwMsgType,
IntPtr hCryptProv,
IntPtr pRecipientInfo,
IntPtr pStreamInfo
);
[DllImport("Crypt32.dll", SetLastError = true)]
internal static extern Boolean CryptMsgClose(
IntPtr hCryptMsg
);
[DllImport("Crypt32.dll", SetLastError = true)]
internal static extern Boolean CryptMsgUpdate(
IntPtr hCryptMsg,
Byte[] pbData,
int cbData,
Boolean fFinal
);
[DllImport("Crypt32.dll", SetLastError = true)]
internal static extern Boolean CryptMsgUpdate(
IntPtr hCryptMsg,
IntPtr pbData,
int cbData,
Boolean fFinal
);
[DllImport("Crypt32.dll", SetLastError = true)]
internal static extern Boolean CryptMsgGetParam(
SafeMsgHandle hCryptMsg,
int dwParamType,
int dwIndex,
SafeNTHeapHandle pvData,
ref int pcbData
);
[DllImport("Crypt32.dll", SetLastError = true)]
internal static extern Boolean CryptMsgGetParam(
SafeMsgHandle hCryptMsg,
int dwParamType,
int dwIndex,
out int pvData,
ref int pcbData
);
[DllImport("Crypt32.dll", SetLastError = true)]
internal static extern Boolean CryptMsgControl(
SafeMsgHandle hCryptMsg,
int dwFlags,
int dwCtrlType,
IntPtr pvCtrlPara
);
[DllImport("Crypt32.dll", SetLastError = true)]
internal static extern Boolean CryptMsgControl(
SafeMsgHandle hCryptMsg,
int dwFlags,
int dwCtrlType,
ref CMSG_SIGNER_ENCODE_INFO pvCtrlPara
);
[DllImport("Crypt32.dll", SetLastError = true)]
internal static extern Boolean CryptMsgControl(
SafeMsgHandle hCryptMsg,
int dwFlags,
int dwCtrlType,
ref BLOB pvCtrlPara
);
[DllImport("Crypt32.dll", SetLastError = true)]
internal static extern Boolean CryptMsgControl(
SafeMsgHandle hCryptMsg,
int dwFlags,
int dwCtrlType,
ref CMSG_CTRL_VERIFY_SIGNATURE_EX_PARA pvCtrlPara
);
[DllImport("Crypt32.dll", SetLastError = true)]
internal static extern Boolean CryptMsgControl(
SafeMsgHandle hCryptMsg,
int dwFlags,
int dwCtrlType,
ref CMSG_CTRL_DECRYPT_PARA pvCtrlPara
);
[DllImport("advapi32.dll", SetLastError = true)]
internal static extern Boolean CryptReleaseContext(
IntPtr hProv,
int dwFlags
);
[DllImport("Crypt32.dll", SetLastError = true)]
internal static extern SafeCertContextHandle CertCreateCertificateContext(
int dwCertEncodingType,
SafeNTHeapHandle pbCertEncoded,
int cbCertEncoded
);
[DllImport("Crypt32.dll", SetLastError = true)]
internal static extern Boolean CertFreeCertificateContext(
IntPtr pCertContext
);
[DllImport("Crypt32.dll", SetLastError = true)]
internal static extern SafeStoreHandle CertOpenStore(
int lpszStoreProvider,
int dwMsgAndCertEncodingType,
IntPtr hCryptProv,
int dwFlags,
SafeMsgHandle pvPara
);
[DllImport("Crypt32.dll", SetLastError = true)]
internal static extern SafeStoreHandle CertOpenSystemStore(
IntPtr hprov,
string szSubsystemProtocol
);
[DllImport("Crypt32.dll", SetLastError = true)]
internal static extern SafeCertContextHandle CertGetSubjectCertificateFromStore(
SafeStoreHandle hCertStore,
int dwCertEncodingType,
SafeNTHeapHandle pCertId
);
[DllImport("Crypt32.dll", SetLastError = true)]
internal static extern IntPtr CertCloseStore(
IntPtr hCertStore,
int dwFlags
);
[DllImport("Crypt32.dll", SetLastError = true)]
internal static extern bool CertGetCertificateContextProperty(
SafeCertContextHandle pCertContext,
int dwPropId,
SafeNTHeapHandle pvData,
ref int pcbData
);
[DllImport("msvcrt.dll", EntryPoint = "memset", CallingConvention = CallingConvention.Cdecl, SetLastError = false)]
internal static extern IntPtr MemSet(
IntPtr ptr,
int value,
int num
);
#endregion
}
}
I hope this helps.
Regards,
Alex (Alejandro Campos Magencio)
Comments
- Anonymous
May 15, 2011
Hi Alejandro,Would you kindly present a solution, where you can retrieve certain attributes of signed executable using P/Invoking. I'm particulary interested how to retrieve Countersignature TimeStamp property and convert it to DateTime object using C#.Thanks. - Anonymous
May 15, 2011
Hi Martin,I would love to do that, but that is out of the scope of this blog. Have you checked this post of mine, where I do all kind of things with these APIs?How to call CryptMsg API in streaming mode - LargeCMS full sampleblogs.msdn.com/.../how-to-call-cryptmsgapi-in-streaming-mode-largecms-full-sample.aspxI hope that helps. If not, you may open a support case with us so we can assist you with that task.Regards,Alex