如何使用CertCreateCertificateContext加载* .CER文件

时间:2018-02-05 22:27:56

标签: access-vba cryptoapi

我必须使用VBA和CryptoAPI才能执行安全的信息交换。作为该过程的一部分,需要使用自定义公钥证书(* .cer)通过CryptoAPI建立上下文/上下文句柄。

我拥有的* .cer文件是" DER编码的二进制X.509"文件。到目前为止,我已经能够使用Windows API调用(CreateFile和ReadFile)将文件加载到二进制数组中。但是,当调用CertCreateCertificateContext()方法时,会引发" ASN.1包标记值" /(CRYPT_E_ANS1_BADTAG)错误。

以下是我迄今为止汇总的代码摘录。

Option Compare Database

Public Declare Function CertCreateCertificateContext Lib "Crypt32.dll" ( _
    ByVal dwCertEncodingType As Long, _
    ByVal pbCertEncoded As String, _
    ByVal cbCertEncoded As Long _
    ) As Long

Public Declare Function CryptDecodeObjectEx Lib "Crypt32.dll" ( _
    ByVal dwCertEncodingType As Long, _
    ByVal lpszStructType As String, _
    ByVal pbEncoded As String, _
    ByVal cbEncoded As Long, _
    ByVal dwFlags As Long, _
    ByVal pDecodePara, _
    ByVal pvStructInfo As Long, _
    ByVal pcbStructInfo As Long _
) As Long

Public Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" ( _
    ByVal lpFileName As String, _
    ByVal dwDesiredAccess As Long, _
    ByVal dwShareMode As Long, _
    lpSecurityAttributes As Long, _
    ByVal dwCreationDisposition As Long, _
    ByVal dwFlagsAndAttributes As Long, _
    hTemplateFile As Long) As Long

Public Declare Function ReadFile Lib "kernel32.dll" ( _
    ByVal hfile As Long, _
    lpBuffer As Any, _
    ByVal nNumberOfBytesToRead As Long, _
    lpNumberOfBytesRead As Long, _
    lpOverlapped As Any) As Long
Public Declare Function GetFileSize Lib "kernel32.dll" (ByVal hfile As Long, lpFileSizeHigh As Long) As Long
'close handle
Private Declare Function CloseHandle Lib "kernel32" (hObject As Long) As Long
'API error function
Private Declare Function GetLastError Lib "kernel32" () As Long


Const GENERIC_READ = &H80000000
Const GENERIC_WRITE = &H40000000
Const FILE_SHARE_READ = &H1
Const FILE_SHARE_WRITE = &H2
Const CREATE_ALWAYS = 2
Const CREATE_NEW = 1
Const OPEN_ALWAYS = 4
Const OPEN_EXISTING = 3
Const TRUNCATE_EXISTING = 5
Const FILE_ATTRIBUTE_ARCHIVE = &H20
Const FILE_ATTRIBUTE_HIDDEN = &H2
Const FILE_ATTRIBUTE_NORMAL = &H80
Const FILE_ATTRIBUTE_READONLY = &H1
Const FILE_ATTRIBUTE_SYSTEM = &H4
Const FILE_FLAG_DELETE_ON_CLOSE = &H4000000
Const FILE_FLAG_NO_BUFFERING = &H20000000
Const FILE_FLAG_OVERLAPPED = &H40000000
Const FILE_FLAG_POSIX_SEMANTICS = &H1000000
Const FILE_FLAG_RANDOM_ACCESS = &H10000000
Const FILE_FLAG_SEQUENTIAL_SCAN = &H8000000
Const FILE_FLAG_WRITE_THROUGH = &H80000000

Const CRYPT_ENCODE_ALLOC_FLAG = &H8000

Const X509_ASN_ENCODING = &H1
Const PKCS_7_ASN_ENCODING = &H10000
Const CertEncodingCombined = &H1 Or &H10000

Const certBufferSize = 65536
Const X509_PUBLIC_KEY_INFO = "X509_PUBLIC_KEY_INFO" & vbNullChar

Private Const INVALID_HANDLE_VALUE = -1

Public Sub foo()
    '-- create file: to open the Cert file (API Documentation: https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858(v=vs.85).aspx)
    Dim certFileHandle As Long
    Dim pathToCert As String

    '-- get file-handle to the CER
    pathToCert = "C:\Projects\Cryptography\SampleCert\public_v2_DER.cer"
    certFileHandle = CreateFile( _
        pathToCert, _
        GENERIC_READ, _
        FILE_SHARE_READ, _
        ByVal CLng(0), _
        OPEN_EXISTING, _
        FILE_ATTRIBUTE_NORMAL, _
        0)
    MsgBox ("Handle to the Cert: " + CStr(certFileHandle))  '-- display handle
    '-- check for error
    If (certFileHandle = INVALID_HANDLE_VALUE) Then
        '-- get last error
        MsgBox ("Error " & CStr(Err.LastDllError) & " during CreateFile!")
        Exit Sub
    End If

    '-- get file size
    Dim highorder As Long, certFileSize As Long
    hiorder = 0  ' initialize the value for high-order half
    certFileSize = GetFileSize(certFileHandle, highorder)  ' read the file's size
    MsgBox ("Cert Size: " & CStr(certFileSize))

    '-- read the file into a byte-array
    Dim longbuffer As Long  ' receives long read from file
    Dim bytes() As Byte
    ReDim bytes(certBufferSize) '--certBufferSize
    Dim numread As Long  ' receives number of bytes read from file
    Dim error As Long

    '-- read the Cer-file as byte-array
    Dim bBytes() As Byte
    ReDim bBytes(certFileSize) As Byte
    error = ReadFile(certFileHandle, bBytes(1), UBound(bBytes), numread, ByVal CLng(0))
    '--     check for errors
    If (error = 0) Then
        MsgBox ("Error " & CStr(Err.LastDllError) & " during ReadFile!")
    Else
        MsgBox ("Got Cert info")
    End If

    '-- do load the context--------------------------
    On Error Resume Next
    Dim certificateAsString As String
    Dim nCertLen As Long
    Dim certContextHandle As Long
    '-- using byte-array, create a Certificate Context
    certContextHandle = CertCreateCertificateContext( _
        CertEncodingCombined, _
        bBytes, _
        certBufferSize _
    )
    MsgBox ("Cert Handle: " & CStr(certContextHandle))  '-- display Context-handle
    MsgBox ("Error " & CStr(Err.LastDllError) & " during CreateCertContext!")   '-- display error
    '-- This is where the error is raised: (-2146881269), CRYPT_E_ASN1_BADTAG (ASN.1 bad tag value met)

    '-- release it
    ReleaseContextHandle (certContextHandle)

    '-- close the file
    CloseHandle (certFileHandle)
End Sub

0 个答案:

没有答案