将GCHandle固定为IntPtr与AllocHGlobal,用于模拟指针指针

时间:2013-09-25 18:32:39

标签: c vb.net pointers interop pinvoke

之间有什么区别
    Dim pCa As IntPtr = 
        GCHandle.Alloc(New IntPtr, GCHandleType.Pinned).AddrOfPinnedObject

    Dim pCa as IntPtr = Marshal.AllocHGlobal(4)
    Marshal.WriteInt32(pCa, Marshal.AllocHGlobal(4))   ' **stach_st_X509

我正在尝试将pkread.c移植到.NET函数PFXtoPEM()

PFXtoPEM()的来源位于libCurlVB.NET-native

这是我到目前为止所做的:

'''Return Type: int, 0 = success or 1 = failure
'''PFXinfile: String
'''password: String
'''PEMoutfile: String
Public Shared Function PFXtoPEM(ByVal PFXinfile As String, ByVal password As String, ByVal PEMoutfile As String) As Integer
    Dim fp As IntPtr = fopen(PFXinfile, "rb")
    Dim p12 As IntPtr
    Dim cert As X509
    Dim ca As stack_st_X509

    Dim pPkey As IntPtr = GCHandle.Alloc(New IntPtr, GCHandleType.Pinned).AddrOfPinnedObject

    Dim pCert As IntPtr = GCHandle.Alloc(New IntPtr, GCHandleType.Pinned).AddrOfPinnedObject

    Dim pCa As IntPtr = GCHandle.Alloc(New IntPtr, GCHandleType.Pinned).AddrOfPinnedObject


    If fp.Equals(IntPtr.Zero) Then
        MessageBox.Show(String.Concat("Error opening file: ", PFXinfile), "Error Converting PFX to PEM", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
        Return 1
    End If

    Dim StdErr As IntPtr = freopen("NUL", "a", IntPtr.op_Explicit(__iob_func.ToInt64() + (Marshal.SizeOf(New FILEp) * 2)))
    Const errbufSize = 8192
    Dim errBuf As IntPtr = Marshal.AllocHGlobal(errbufSize)

    ERR_load_crypto_strings()
    memset(errBuf, Asc(vbNullChar), errbufSize)
    setvbuf(StdErr, errBuf, _IOFBF, errbufSize)

    OPENSSL_add_all_algorithms_noconf()

    Try
        p12 = d2i_PKCS12_fp(fp, IntPtr.Zero)
        If p12.Equals(IntPtr.Zero) Then Throw New SEHException("d2i_PKCS12_fp didn't throw but also didn't succeed")
    Catch ex As SEHException
        ERR_print_errors_fp(StdErr)
        MessageBox.Show(String.Concat("Error reading PKCS#12 file. " & vbNewLine, Marshal.PtrToStringAnsi(errBuf)), "Error Converting PFX to PEM", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
        Return 1
    End Try

    fclose(fp)

    Try

        PKCS12_parse(p12, password, pPkey, pCert, pCa)

    Catch ex As Exception
        ERR_print_errors_fp(StdErr)
        MessageBox.Show(String.Concat("Error parsing PKCS#12 file, check pfx password. " & vbNewLine, Marshal.PtrToStringAnsi(errBuf)), "Error Converting PFX to PEM", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
        Return 1
    End Try

    PKCS12_free(p12)

    fp = fopen(PEMoutfile, "w")
    If fp.Equals(IntPtr.Zero) Then
        MessageBox.Show(String.Concat("Error opening file: ", PEMoutfile), "Error Converting PFX to PEM", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
        Return 1
    End If


    If Not IntPtr.op_Explicit(Marshal.ReadInt32(pPkey)).Equals(IntPtr.Zero) Then
        fprintf(fp, "****Private Key****" & vbNewLine)
        PEM_write_PrivateKey(fp, IntPtr.op_Explicit(Marshal.ReadInt32(pPkey)), Nothing, Nothing, Nothing, Nothing, Nothing)
    End If


    If Not IntPtr.op_Explicit(Marshal.ReadInt32(pCert)).Equals(IntPtr.Zero) Then
        fprintf(fp, "***User Certificate***" & vbNewLine)
        fprintf(fp, "subject=")
        fprintf(fp, X509_NAME_oneline(IntPtr.op_Explicit(Marshal.ReadInt32(IntPtr.op_Explicit(Marshal.ReadInt32(Marshal.ReadInt32(pCert)) + 20))), 0, 0))
        fprintf(fp, vbNewLine & "issuer=")
        fprintf(fp, X509_NAME_oneline(IntPtr.op_Explicit(Marshal.ReadInt32(IntPtr.op_Explicit(Marshal.ReadInt32(Marshal.ReadInt32(pCert)) + 12))), 0, 0))
        fprintf(fp, vbNewLine)
        PEM_write_X509_AUX(fp, IntPtr.op_Explicit((Marshal.ReadInt32(pCert))))
    End If


    If Not IntPtr.op_Explicit(Marshal.ReadInt32(pCert)).Equals(IntPtr.Zero) Then
        ca = Marshal.PtrToStructure(IntPtr.op_Explicit(Marshal.ReadInt32(pCa)), GetType(stack_st_X509))
        fprintf(fp, "****CA Certificates****" & vbNewLine)

        For i = 0 To ca.stack.num - 1

            cert = Marshal.PtrToStructure(IntPtr.op_Explicit(Marshal.ReadInt32(IntPtr.op_Explicit(ca.stack.data.ToInt32 + 4 * i))), GetType(X509))
            Dim certGChandle As GCHandle = GCHandle.Alloc(cert.cert_info, GCHandleType.Pinned)
            Dim pCertInfo As IntPtr = certGChandle.AddrOfPinnedObject

            fprintf(fp, "subject=")
            fprintf(fp, X509_NAME_oneline(IntPtr.op_Explicit(Marshal.ReadInt32(IntPtr.op_Explicit(Marshal.ReadInt32(pCertInfo) + 20))), 0, 0))
            fprintf(fp, vbNewLine & "issuer=")
            fprintf(fp, X509_NAME_oneline(IntPtr.op_Explicit(Marshal.ReadInt32(IntPtr.op_Explicit(Marshal.ReadInt32(pCertInfo) + 12))), 0, 0))
            fprintf(fp, vbNewLine)
            PEM_write_X509_AUX(fp, IntPtr.op_Explicit(Marshal.ReadInt32(IntPtr.op_Explicit(ca.stack.data.ToInt32 + 4 * i))))
            certGChandle.Free()

        Next

    End If

    fclose(fp)


    Marshal.FreeHGlobal(errBuf)

    Return 0

End Function

现在,此功能正常工作,它成功地将PFX转换为PEM,并提供了正确的密码。 但是,我不想用pPkey初始化pCertpCaGCHandle。所以我改成了这个:

'''Return Type: int, 0 = success or 1 = failure
'''PFXinfile: String
'''password: String
'''PEMoutfile: String
Public Shared Function PFXtoPEM(ByVal PFXinfile As String, ByVal password As String, ByVal PEMoutfile As String) As Integer
    Dim fp As IntPtr = fopen(PFXinfile, "rb")
    Dim p12 As IntPtr
    Dim cert As X509
    Dim ca As stack_st_X509

    Dim pPkey As IntPtr = Marshal.AllocHGlobal(4)
    Marshal.WriteInt32(pPkey, Marshal.AllocHGlobal(4)) ' **EVP_PKEY
    Dim pCert As IntPtr = Marshal.AllocHGlobal(4)
    Marshal.WriteInt32(pCert, Marshal.AllocHGlobal(4)) ' **X509
    Dim pCa As IntPtr = Marshal.AllocHGlobal(4)
    Marshal.WriteInt32(pCa, Marshal.AllocHGlobal(4))   ' **stach_st_X509

    '...

    fclose(fp)

    Marshal.FreeHGlobal(IntPtr.op_Explicit(Marshal.ReadInt32(pPkey)))
    Marshal.FreeHGlobal(IntPtr.op_Explicit(Marshal.ReadInt32(pCert)))
    Marshal.FreeHGlobal(IntPtr.op_Explicit(Marshal.ReadInt32(pCa)))
    Marshal.FreeHGlobal(pPkey)
    Marshal.FreeHGlobal(pCert)
    Marshal.FreeHGlobal(pCa)

    Marshal.FreeHGlobal(errBuf)

    Return 0

End Function

现在这不起作用。 PKCS12_parse

<DllImport("libeay32.dll", _
SetLastError:=True, _
CallingConvention:=CallingConvention.Cdecl)> _
Public Shared Function PKCS12_parse( _
ByVal p12 As IntPtr, _
<MarshalAs(UnmanagedType.LPStr)> ByVal pass As String, _
ByVal pkey As IntPtr, _
ByVal cert As IntPtr, _
ByVal ca As IntPtr) As Integer
End Function 

抛出System.AccessViolationException

然而这有效:

'''Return Type: int, 0 = success or 1 = failure
'''PFXinfile: String
'''password: String
'''PEMoutfile: String
Public Shared Function PFXtoPEM(ByVal PFXinfile As String, ByVal password As String, ByVal PEMoutfile As String) As Integer
    Dim fp As IntPtr = fopen(PFXinfile, "rb")
    Dim p12 As IntPtr
    Dim cert As X509
    Dim ca As stack_st_X509

    Dim pPkey As IntPtr = Marshal.AllocHGlobal(4)
    Marshal.WriteInt32(pPkey, Marshal.AllocHGlobal(4)) ' **EVP_PKEY
    Dim pCert As IntPtr = Marshal.AllocHGlobal(4)
    Marshal.WriteInt32(pCert, Marshal.AllocHGlobal(4)) ' **X509
    Dim pCa As IntPtr = GCHandle.Alloc(New IntPtr, GCHandleType.Pinned).AddrOfPinnedObject

    '...

    fclose(fp)

    Debug.Print(IntPtr.op_Explicit(Marshal.ReadInt32(pPkey)))
    Marshal.FreeHGlobal(IntPtr.op_Explicit(Marshal.ReadInt32(pPkey)))
    Marshal.FreeHGlobal(IntPtr.op_Explicit(Marshal.ReadInt32(pCert)))
    Marshal.FreeHGlobal(pPkey)
    Marshal.FreeHGlobal(pCert)

    Marshal.FreeHGlobal(errBuf)

    Return 0

End Function

0 个答案:

没有答案