Share via


P/Invoking CryptoAPI in .NET (VB.NET version)

Hi, welcome back,

This is a continuation of my previous post, P/Invoking CryptoAPI in .NET (C# version).

Here you have the most common P/Invoke CryptoAPI declarations I've successfully used in the past, but this time for VB.NET ( Note: I've included a couple of auxiliary functions which may be of help, too. CertContextFromCertSubject gets a certificate context from a certificate in MY/Personal certificate store, and RSACryptoServiceProviderFromCertContext creates an RSACryptoServiceProvider object from that certificate context. I don't have them in C#, but they should be easy to convert):

 

<SAMPLE>

 Imports System.Runtime.InteropServices
Imports System.Security.Cryptography
Imports System.ComponentModel

Public Class Crypto

#Region "CONSTS"

    ' #define BUFSIZE   1024
    Public Const BUFSIZE As Int32 = 1024

    ' #define AT_KEYEXCHANGE        1
    Public Const AT_KEYEXCHANGE As Int32 = 1

    ' #define AT_SIGNATURE      2
    Public Const AT_SIGNATURE As Int32 = 2

    ' #define CERT_STORE_PROV_SYSTEM_W      ((LPCSTR) 10)
    Public Const CERT_STORE_PROV_SYSTEM_W As Int32 = 10

    ' #define CERT_STORE_PROV_SYSTEM        CERT_STORE_PROV_SYSTEM_W
    Public Const CERT_STORE_PROV_SYSTEM As Int32 = CERT_STORE_PROV_SYSTEM_W

    ' #define CERT_SYSTEM_STORE_CURRENT_USER_ID     1
    Public Const CERT_SYSTEM_STORE_CURRENT_USER_ID As Int32 = 1

    ' #define CERT_SYSTEM_STORE_LOCATION_SHIFT      16
    Public Const CERT_SYSTEM_STORE_LOCATION_SHIFT As Int32 = 16

    ' #define CERT_SYSTEM_STORE_CURRENT_USER        \
    '   (CERT_SYSTEM_STORE_CURRENT_USER_ID << CERT_SYSTEM_STORE_LOCATION_SHIFT)
    Public Const CERT_SYSTEM_STORE_CURRENT_USER As Int32 = _
        CERT_SYSTEM_STORE_CURRENT_USER_ID << CERT_SYSTEM_STORE_LOCATION_SHIFT

    ' #define CERT_PERSONAL_STORE_NAME      L"My"
    Public Const CERT_PERSONAL_STORE_NAME As String = "My"

    ' #define X509_ASN_ENCODING     0x00000001
    Public Const X509_ASN_ENCODING As Int32 = &H1

    ' #define PKCS_7_ASN_ENCODING       0x00010000
    Public Const PKCS_7_ASN_ENCODING As Int32 = &H10000

    ' #define MY_TYPE       (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
    Public Const MY_TYPE As Int32 = PKCS_7_ASN_ENCODING + X509_ASN_ENCODING

    ' #define CERT_COMPARE_ANY      0
    Public Const CERT_COMPARE_ANY As Int32 = 0

    ' #define CERT_COMPARE_SHA1_HASH        1
    Public Const CERT_COMPARE_SHA1_HASH As Int32 = 1

    ' #define CERT_COMPARE_SHIFT        16
    Public Const CERT_COMPARE_SHIFT As Int32 = 16

    ' #define CERT_FIND_SHA1_HASH       (CERT_COMPARE_SHA1_HASH << CERT_COMPARE_SHIFT)
    Public Const CERT_FIND_SHA1_HASH As Int32 = CERT_COMPARE_SHA1_HASH << CERT_COMPARE_SHIFT

    ' #define CERT_FIND_HASH        CERT_FIND_SHA1_HASH
    Public Const CERT_FIND_HASH As Int32 = CERT_FIND_SHA1_HASH

    ' #define CERT_FIND_ANY     (CERT_COMPARE_ANY << CERT_COMPARE_SHIFT)
    Public Const CERT_FIND_ANY As Int32 = CERT_COMPARE_ANY << CERT_COMPARE_SHIFT

    ' #define CERT_COMPARE_NAME   2
    Public Const CERT_COMPARE_NAME As Int32 = 2

    ' #define CERT_INFO_SUBJECT_FLAG  7
    Public Const CERT_INFO_SUBJECT_FLAG As Int32 = 7

    ' #define CERT_FIND_SUBJECT_NAME    (CERT_COMPARE_NAME << CERT_COMPARE_SHIFT | CERT_INFO_SUBJECT_FLAG)
    Public Const CERT_FIND_SUBJECT_NAME As Int32 = (CERT_COMPARE_NAME << CERT_COMPARE_SHIFT) + CERT_INFO_SUBJECT_FLAG

    ' #define CERT_COMPARE_NAME_STR_W     8
    Public Const CERT_COMPARE_NAME_STR_W As Int32 = 8

    ' #define CERT_FIND_SUBJECT_STR_W   \
    '   (CERT_COMPARE_NAME_STR_W << CERT_COMPARE_SHIFT | CERT_INFO_SUBJECT_FLAG)
    Public Const CERT_FIND_SUBJECT_STR_W As Int32 = (CERT_COMPARE_NAME_STR_W << CERT_COMPARE_SHIFT) + CERT_INFO_SUBJECT_FLAG

    ' #define CERT_FIND_SUBJECT_STR CERT_FIND_SUBJECT_STR_W
    Public Const CERT_FIND_SUBJECT_STR As Int32 = CERT_FIND_SUBJECT_STR_W

    ' #define CERT_CLOSE_STORE_CHECK_FLAG       0x00000002
    Public Const CERT_CLOSE_STORE_CHECK_FLAG As Int32 = &H2

    ' #define ALG_CLASS_HASH        (4 << 13)
    Public Const ALG_CLASS_HASH As Int32 = 4 << 13

    ' #define ALG_TYPE_ANY      (0)
    Public Const ALG_TYPE_ANY As Int32 = 0

    ' #define ALG_SID_MD5       3
    Public Const ALG_SID_MD5 As Int32 = 3

    ' #define ALG_SID_SHA1      4
    Public Const ALG_SID_SHA1 As Int32 = 4

    ' #define CALG_MD5      (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_MD5)
    Public Const CALG_MD5 As Int32 = ALG_CLASS_HASH + ALG_TYPE_ANY + ALG_SID_MD5

    ' #define CALG_SHA1     (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA1)
    Public Const CALG_SHA1 As Int32 = ALG_CLASS_HASH + ALG_TYPE_ANY + ALG_SID_SHA1

    ' #define PP_KEYEXCHANGE_PIN        32
    Public Const PP_KEYEXCHANGE_PIN As Int32 = 32

    ' #define PP_SIGNATURE_PIN      33
    Public Const PP_SIGNATURE_PIN As Int32 = 33

    ' #define PROV_RSA_FULL     1
    Public Const PROV_RSA_FULL As Int32 = &H1

    ' #define CRYPT_VERIFYCONTEXT       0xF0000000
    Public Const CRYPT_VERIFYCONTEXT As Int32 = &HF0000000

    ' #define CERT_KEY_PROV_INFO_PROP_ID    2
    Public Const CERT_KEY_PROV_INFO_PROP_ID As Int32 = 2

#End Region

#Region "STRUCTS"

    ' typedef struct _CRYPTOAPI_BLOB {
    '   DWORD   cbData;
    '   BYTE    *pbData;
    ' } CRYPT_HASH_BLOB, CRYPT_INTEGER_BLOB, 
    '   CRYPT_OBJID_BLOB, CERT_NAME_BLOB;
    <StructLayout(LayoutKind.Sequential)> _
    Public Structure CRYPTOAPI_BLOB
        Public cbData As Int32
        Public pbData As IntPtr
    End Structure

    ' typedef struct _CRYPT_ALGORITHM_IDENTIFIER {
    '   LPSTR               pszObjId;
    '   CRYPT_OBJID_BLOB    Parameters;
    ' } CRYPT_ALGORITHM_IDENTIFIER;
    <StructLayout(LayoutKind.Sequential)> _
    Public Structure CRYPT_ALGORITHM_IDENTIFIER
        <MarshalAs(UnmanagedType.LPStr)> Public pszObjId As String
        Public Parameters As CRYPTOAPI_BLOB
    End Structure

    ' typedef struct _FILETIME {
    '   DWORD dwLowDateTime;
    '   DWORD dwHighDateTime;
    ' } FILETIME;
    <StructLayout(LayoutKind.Sequential)> _
    Public Structure FILETIME
        Public dwLowDateTime As Int32
        Public dwHighDateTime As Int32
    End Structure

    ' typedef struct _CRYPT_BIT_BLOB {
    '   DWORD   cbData;
    '   BYTE    *pbData;
    '   DWORD   cUnusedBits;
    ' } CRYPT_BIT_BLOB;
    <StructLayout(LayoutKind.Sequential)> _
    Public Structure CRYPT_BIT_BLOB
        Public cbData As Int32
        Public pbData As Byte()
        Public cUnusedBits As Int32
    End Structure

    ' typedef struct _CERT_PUBLIC_KEY_INFO {
    '   CRYPT_ALGORITHM_IDENTIFIER    Algorithm;
    '   CRYPT_BIT_BLOB                PublicKey;
    ' } CERT_PUBLIC_KEY_INFO;
    <StructLayout(LayoutKind.Sequential)> _
    Public Structure CERT_PUBLIC_KEY_INFO
        Public Algorithm As CRYPT_ALGORITHM_IDENTIFIER
        Public PublicKey As CRYPT_BIT_BLOB
    End Structure

    ' typedef struct _CERT_INFO {
    '   DWORD                       dwVersion;
    '   CRYPT_INTEGER_BLOB          SerialNumber;
    '   CRYPT_ALGORITHM_IDENTIFIER  SignatureAlgorithm;
    '   CERT_NAME_BLOB              Issuer;
    '   FILETIME                    NotBefore;
    '   FILETIME                    NotAfter;
    '   CERT_NAME_BLOB              Subject;
    '   CERT_PUBLIC_KEY_INFO        SubjectPublicKeyInfo;
    '   CRYPT_BIT_BLOB              IssuerUniqueId;
    '   CRYPT_BIT_BLOB              SubjectUniqueId;
    '   DWORD                       cExtension;
    '   PCERT_EXTENSION             rgExtension;
    ' } CERT_INFO;
    <StructLayout(LayoutKind.Sequential)> _
    Public Structure CERT_INFO
        Public dwVersion As Int32
        Public SerialNumber As CRYPTOAPI_BLOB
        Public SignatureAlgorithm As CRYPT_ALGORITHM_IDENTIFIER
        Public Issuer As CRYPTOAPI_BLOB
        Public NotBefore As FILETIME
        Public NotAfter As FILETIME
        Public Subject As CRYPTOAPI_BLOB
        Public SubjectPublicKeyInfo As CERT_PUBLIC_KEY_INFO
        Public IssuerUniqueId As CRYPT_BIT_BLOB
        Public SubjectUniqueId As CRYPT_BIT_BLOB
        Public cExtension As Int32
        Public rgExtension As IntPtr
    End Structure

    ' typedef struct _CERT_CONTEXT {
    '   DWORD                   dwCertEncodingType;
    '   BYTE                    *pbCertEncoded;
    '   DWORD                   cbCertEncoded;
    '   PCERT_INFO              pCertInfo;
    '   HCERTSTORE              hCertStore;
    ' } CERT_CONTEXT;
    <StructLayout(LayoutKind.Sequential)> _
    Public Structure CERT_CONTEXT
        Public dwCertEncodingType As Int32
        Public pbCertEncoded As Byte()
        Public cbCertEncoded As Int32
        Public pCertInfo As IntPtr
        Public hCertStore As IntPtr
    End Structure

#End Region

#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 Shared Function CertOpenStore( _
        ByVal lpszStoreProvider As Int32, _
        ByVal dwMsgAndCertEncodingType As Int32, _
        ByVal hCryptProv As IntPtr, _
        ByVal dwFlags As Int32, _
        ByVal pvPara As String _
    ) As IntPtr
    End Function

    ' HCERTSTORE WINAPI CertOpenSystemStore(
    '   HCRYPTPROV hprov,
    '   LPTCSTR szSubsystemProtocol
    ');
    <DllImport("Crypt32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
    Public Shared Function CertOpenSystemStore( _
        ByVal hprov As IntPtr, _
        ByVal szSubsystemProtocol As String _
    ) As IntPtr
    End Function

    ' PCCERT_CONTEXT WINAPI CertFindCertificateInStore(
    '   HCERTSTORE hCertStore,
    '   DWORD dwCertEncodingType,
    '   DWORD dwFindFlags,
    '   DWORD dwFindType,
    '   const void* pvFindPara,
    '   PCCERT_CONTEXT pPrevCertContext
    ' );
    '<DllImport("Crypt32.dll", SetLastError:=True)> _
    'Public Shared Function CertFindCertificateInStore( _
    '    ByVal hCertStore As IntPtr, _
    '    ByVal dwCertEncodingType As Int32, _
    '    ByVal dwFindFlags As Int32, _
    '    ByVal dwFindType As Int32, _
    '    ByRef pvFindPara As CRYPTOAPI_BLOB, _
    '    ByVal pPrevCertContext As IntPtr _
    ') As IntPtr
    'End Function
    <DllImport("Crypt32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
    Public Shared Function CertFindCertificateInStore( _
        ByVal hCertStore As IntPtr, _
        ByVal dwCertEncodingType As Int32, _
        ByVal dwFindFlags As Int32, _
        ByVal dwFindType As Int32, _
        ByVal pvFindPara As String, _
        ByVal pPrevCertContext As IntPtr _
    ) As IntPtr
    End Function

    ' BOOL WINAPI CryptAcquireCertificatePrivateKey(
    '   PCCERT_CONTEXT pCert,
    '   DWORD dwFlags,
    '   void* pvReserved,
    '   HCRYPTPROV* phCryptProv,
    '   DWORD* pdwKeySpec,
    '   BOOL* pfCallerFreeProv
    ' );
    <DllImport("Crypt32.dll", SetLastError:=True)> _
    Public Shared Function CryptAcquireCertificatePrivateKey( _
        ByVal pCert As IntPtr, _
        ByVal dwFlags As Int32, _
        ByVal pvReserverd As IntPtr, _
        ByRef phCryptProv As IntPtr, _
        ByRef pdwKeySpec As Int32, _
        ByRef pfCallerFreeProv As Boolean _
    ) As Boolean
    End Function

    ' BOOL WINAPI CertCloseStore(
    '   HCERTSTORE hCertStore,
    '   DWORD dwFlags
    ' );
    <DllImport("Crypt32.dll", SetLastError:=True)> _
    Public Shared Function CertCloseStore( _
        ByVal hCertStore As IntPtr, _
        ByVal dwFlags As Int32 _
    ) As Boolean
    End Function

    ' BOOL WINAPI CryptReleaseContext(
    '   HCRYPTPROV hProv,
    '   DWORD dwFlags
    ' );
    <DllImport("Advapi32.dll", SetLastError:=True)> _
    Public Shared Function CryptReleaseContext( _
        ByVal hProv As IntPtr, _
        ByVal dwFlags As Int32 _
    ) As Boolean
    End Function

    ' BOOL WINAPI CryptCreateHash(
    '   HCRYPTPROV hProv,
    '   ALG_ID Algid,
    '   HCRYPTKEY hKey,
    '   DWORD dwFlags,
    '   HCRYPTHASH* phHash
    ' );
    <DllImport("advapi32.dll", SetLastError:=True)> _
    Public Shared Function CryptCreateHash( _
        ByVal hProv As IntPtr, _
        ByVal Algid As Int32, _
        ByVal hKey As IntPtr, _
        ByVal dwFlags As Int32, _
        ByRef phHash As IntPtr _
    ) As Boolean
    End Function

    ' BOOL WINAPI CryptDestroyHash(
    '   HCRYPTHASH hHash
    ' );
    <DllImport("advapi32.dll", SetLastError:=True)> _
    Public Shared Function CryptDestroyHash( _
        ByVal hHash As IntPtr _
    ) As Boolean
    End Function

    ' BOOL WINAPI CryptSetProvParam(
    '   HCRYPTPROV hProv,
    '   DWORD dwParam,
    '   BYTE* pbData,
    '   DWORD dwFlags
    ' );
    <DllImport("advapi32.dll", SetLastError:=True)> _
    Public Shared Function CryptSetProvParam( _
        ByVal hProv As IntPtr, _
        ByVal dwParam As Int32, _
        ByVal pbData As Byte(), _
        ByVal dwFlags As Int32 _
    ) As Boolean
    End Function

    ' BOOL WINAPI CryptHashData(
    '   HCRYPTHASH hHash,
    '   BYTE* pbData,
    '   DWORD dwDataLen,
    '   DWORD dwFlags
    ' ); 
    <DllImport("advapi32.dll", SetLastError:=True)> _
    Public Shared Function CryptHashData( _
        ByVal hHash As IntPtr, _
        ByVal pbData As Byte(), _
        ByVal dwDataLen As Int32, _
        ByVal dwFlags As Int32 _
    ) As Boolean
    End Function

    ' BOOL WINAPI CryptSignHash(
    '   HCRYPTHASH hHash,
    '   DWORD dwKeySpec,
    '   LPCTSTR sDescription,
    '   DWORD dwFlags,
    '   BYTE* pbSignature,
    '   DWORD* pdwSigLen
    ' );
    <DllImport("advapi32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
    Public Shared Function CryptSignHash( _
        ByVal hHash As IntPtr, _
        ByVal dwKeySpec As Int32, _
        ByVal sDescription As String, _
        ByVal dwFlags As Int32, _
        ByVal pbSignature As Byte(), _
        ByRef pdwSigLen As Int32 _
    ) As Boolean
    End Function

    ' BOOL WINAPI CertFreeCertificateContext(
    '   PCCERT_CONTEXT pCertContext
    ' );
    <DllImport("Crypt32.dll", SetLastError:=True)> _
    Public Shared Function CertFreeCertificateContext( _
        ByVal pCertContext As IntPtr _
    ) As Boolean
    End Function

    ' BOOL WINAPI CryptAcquireContext(
    '   HCRYPTPROV* phProv,
    '   LPCTSTR pszContainer,
    '   LPCTSTR pszProvider,
    '   DWORD dwProvType,
    '   DWORD dwFlags
    ' );
    <DllImport("advapi32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
    Public Shared Function CryptAcquireContext( _
        ByRef hProv As IntPtr, _
        ByVal pszContainer As String, _
        ByVal pszProvider As String, _
        ByVal dwProvType As Int32, _
        ByVal dwFlags As Int32 _
    ) As Boolean
    End Function

    ' BOOL WINAPI CryptImportPublicKeyInfo(
    '   HCRYPTPROV hCryptProv,
    '   DWORD dwCertEncodingType,
    '   PCERT_PUBLIC_KEY_INFO pInfo,
    '   HCRYPTKEY* phKey
    ' );
    <DllImport("crypt32.dll", SetLastError:=True)> _
    Public Shared Function CryptImportPublicKeyInfo( _
        ByVal hCryptProv As IntPtr, _
        ByVal dwCertEncodingType As Int32, _
        ByVal pInfo As IntPtr, _
        ByRef phKey As IntPtr _
    ) As Boolean
    End Function

    ' BOOL WINAPI CryptVerifySignature(
    '   HCRYPTHASH hHash,
    '   BYTE* pbSignature,
    '   DWORD dwSigLen,
    '   HCRYPTKEY hPubKey,
    '   LPCTSTR sDescription,
    '   DWORD dwFlags
    ' );
    <DllImport("advapi32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
    Public Shared Function CryptVerifySignature( _
        ByVal hHash As IntPtr, _
        ByVal pbSignature As Byte(), _
        ByVal dwSigLen As Int32, _
        ByVal hPubKey As IntPtr, _
        ByVal sDescription As String, _
        ByVal dwFlags As Int32 _
    ) As Boolean
    End Function

    ' BOOL WINAPI CryptDestroyKey(
    '   HCRYPTKEY hKey
    ' );
    <DllImport("advapi32.dll", SetLastError:=True)> _
    Public Shared Function CryptDestroyKey( _
        ByVal hKey As IntPtr _
    ) As Boolean
    End Function

    ' BOOL WINAPI CertGetCertificateContextProperty(
    '   PCCERT_CONTEXT pCertContext,
    '   DWORD dwPropId,
    '   void* pvData,
    '   DWORD* pcbData
    ' );
    <DllImport("crypt32.dll", SetLastError:=True)> _
    Public Shared Function CertGetCertificateContextProperty( _
        ByVal pCertContext As IntPtr, _
        ByVal dwPropId As Int32, _
        ByVal pvData As IntPtr, _
        ByRef pcbData As Int32 _
    ) As Boolean
    End Function

    ' PCCERT_CONTEXT WINAPI CertEnumCertificatesInStore(
    '   HCERTSTORE hCertStore,
    '   PCCERT_CONTEXT pPrevCertContext
    ');
    <DllImport("crypt32.dll", SetLastError:=True)> _
    Public Shared Function CertEnumCertificatesInStore( _
        ByVal hCertStore As IntPtr, _
        ByVal pPrevCertContext As IntPtr _
    ) As IntPtr
    End Function

    ' PCCERT_CONTEXT WINAPI CertDuplicateCertificateContext(
    '   PCCERT_CONTEXT pCertContext
    ');
    <DllImport("crypt32.dll", SetLastError:=True)> _
    Public Shared Function CertDuplicateCertificateContext( _
        ByVal pCertContext As IntPtr _
    ) As IntPtr
    End Function

#End Region

#Region "FUNCTIONS"

    Public Shared Function CertContextFromCertSubject(ByVal subject As String) As IntPtr

        ' Variables
        '
        Dim bResult As Boolean = False
        Dim hStoreHandle As IntPtr = IntPtr.Zero
        Dim pCertContext As IntPtr = IntPtr.Zero

        Try

            ' Open the certificate store.
            '
            hStoreHandle = CertOpenSystemStore( _
                0, _
                CERT_PERSONAL_STORE_NAME _
            )
            If (hStoreHandle.Equals(IntPtr.Zero)) Then
                Throw New Exception("CertOpenStore error", New Win32Exception(Marshal.GetLastWin32Error()))
            End If

            ' Get a certificate that matches the search criteria.
            ' 
            pCertContext = CertFindCertificateInStore( _
                hStoreHandle, _
                MY_TYPE, _
                0, _
                CERT_FIND_SUBJECT_STR, _
                subject, _
                IntPtr.Zero _
            )
            If (pCertContext.Equals(IntPtr.Zero)) Then
                Throw New Exception("CertFindCertificateInStore error", New Win32Exception(Marshal.GetLastWin32Error()))
            End If

            Return pCertContext

        Catch ex As Exception

            ' Any errors? Show them.
            '
            If (ex.InnerException Is Nothing) Then
                MessageBox.Show(ex.Message)
            Else
                MessageBox.Show(ex.Message + " --> " + ex.InnerException.Message)
            End If

        Finally

            ' Clean up and free memory.
            '
            If (Not hStoreHandle.Equals(IntPtr.Zero)) Then
                bResult = CertCloseStore( _
                    hStoreHandle, _
                    CERT_CLOSE_STORE_CHECK_FLAG _
                )
            End If

        End Try

        Return Nothing

    End Function

    ' Converted to VB.NET from KB article 320602
    '
    Public Shared Function RSACryptoServiceProviderFromCertContext(ByVal pCertContext As IntPtr) As RSACryptoServiceProvider

        'Determine the size of the buffer that you need to allocate.
        '
        Dim cbData As Int32 = 0
        Dim fStatus As Boolean = CertGetCertificateContextProperty( _
            pCertContext, _
            CERT_KEY_PROV_INFO_PROP_ID, _
            0, _
            cbData)

        If (Not fStatus) Then
            MessageBox.Show("CertGetCertificateContextProperty error --> " + Marshal.GetLastWin32Error().ToString())

            ' Get the CERT_KEY_PROV_HANDLE_PROP_ID value and the HCRYPTPROV value.
            '
            cbData = 4
            Dim pCryptKeyProvInfo As IntPtr = Marshal.AllocHGlobal(New IntPtr(cbData))
            fStatus = CertGetCertificateContextProperty( _
                pCertContext, _
                CERT_KEY_PROV_INFO_PROP_ID, _
                pCryptKeyProvInfo, _
                cbData)

            If (Not fStatus) Then
                MessageBox.Show("CertGetCertificateContextProperty error --> " + Marshal.GetLastWin32Error().ToString())
            End If
            Return Nothing

        End If

        If (Not cbData = 0) Then

            ' Allocate an unmanaged buffer to store the CRYPT_KEY_PROV_INFO structure.
            '
            Dim pCryptKeyProvInfo As IntPtr = Marshal.AllocHGlobal(cbData)

            ' Get the CRYPT_KEY_PROV_INFO structure.
            '
            fStatus = CertGetCertificateContextProperty( _
                pCertContext, _
                CERT_KEY_PROV_INFO_PROP_ID, _
                pCryptKeyProvInfo, _
                cbData)

            If (Not fStatus) Then
                MessageBox.Show("CertGetCertificateContextProperty failed: " + Marshal.GetLastWin32Error().ToString())
                Marshal.FreeHGlobal(pCryptKeyProvInfo)
            Else

                ' Build a CspParameters object with the provider type, the provider name,
                ' and the container name from the CRYPT_KEY_PROV_INFO structure.
                ' The pointer to the container name is the first DWORD in the CRYPT_KEY_PROV_INFO
                ' structure, the pointer to the provider name is the second DWORD, and
                ' the provider type is the third DWORD.
                '
                Try
                    Dim CspParams As CspParameters = New CspParameters( _
                        Marshal.ReadInt32(New IntPtr(pCryptKeyProvInfo.ToInt32 + 8)), _
                        Marshal.PtrToStringUni(New IntPtr(Marshal.ReadInt32(New IntPtr(pCryptKeyProvInfo.ToInt32 + 4)))), _
                        Marshal.PtrToStringUni(New IntPtr(Marshal.ReadInt32(pCryptKeyProvInfo))))

                    ' Free the unmanaged CRYPT_KEY_PROV_INFO buffer.
                    '
                    Marshal.FreeHGlobal(pCryptKeyProvInfo)
                    Return New RSACryptoServiceProvider(CspParams)

                Catch ex As Exception
                    MessageBox.Show(ex.Message)
                End Try

            End If
        End If
        Return Nothing

    End Function

#End Region

End Class

</SAMPLE>

 

I hope this helps.

Cheers,

 

Alex (Alejandro Campos Magencio)

Comments

  • Anonymous
    November 25, 2007
    Should these include a StructLayoutAttribute on the public structure declarations?
  • Anonymous
    November 26, 2007
    As far as I know there is no need for that. C#, Visual Basic.NET, and C++ compilers apply the Sequential layout value to structures by default. The LayoutKind value Sequential is used to force the members to be laid out sequentially in the order they appear. So that would be enough for our purposes.Of course you may use StructLayoutAttribute and it would be ok, too.More info here:StructLayoutAttribute Classhttp://msdn2.microsoft.com/en-us/library/system.runtime.interopservices.structlayoutattribute.aspxThx,Alex
  • Anonymous
    February 07, 2008
    I just realized that all the text between < and > that I had in the code had been removed when I pasted the code in the post, so the code was missing things like <StructLayout(LayoutKind.Sequential)> or <DllImport("advapi32.dll", CharSet:=CharSet.Auto, SetLastError:=True)>. I've solved that already. Sorry!!! I think that was what Duncan meant with his comment long time ago... Thx Duncan!Cheers,Alex
  • Anonymous
    April 05, 2010
    Some offtopic but..you can add a root certifacte with visual basic with:        Dim almacenRoot As New X509Store("ROOT")        almacenRoot.Open(OpenFlags.MaxAllowed)        Dim cert As New X509Certificate2(My.Resources.fnmt)        almacenRoot.Add(cert)        Dim cert2 As New X509Certificate2(My.Resources.dgsfp)        almacenRoot.Add(cert2)        almacenRoot.Close()        msgMensaje.Mostrar("Certificados incluidos")
  • Anonymous
    September 25, 2011
    Thank you very much Alejandro. You have facilitate my work a lot. I had to sign and timestamp a PDF by using itextsharp and your code has been very useful.Best regardsManuel