Freigeben über


P/Invoking CryptoAPI in .NET. Part 2 (C#)

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