从vb.net调用时,CryptEncrypt / CryptDecrypt WinAPI函数失败

时间:2013-11-15 09:31:51

标签: vb.net winapi pinvoke cryptoapi

对以下任何帮助都非常感谢.....

我有一些我继承的C ++代码,它解密某些结构/字节数组;我一直在尝试在VB.net中编写一个测试程序,它使用相同的函数来完全模仿C ++解密例程,即。使用WinAPI加密调用;在测试中,CryptAcquireContext,CryptCreateHash,CryptHashData和CryptDeriveKey都成功了;

但是,即使在最简单的情况下,CryptEncrypt和CryptDecrypt函数都会因Invalid Parameter错误而失败;

(我知道System.Security.Cryptography命名空间......我将诉诸于此......但C ++代码包含带有联合的结构,并且为了测试,最好先尝试WinAPI路由)

示例代码如下......我在Win7x64 sp1上,vs 2010 sp1 ...

Private Sub cmdTest(sender As System.Object, e As System.EventArgs) Handles cmdtest.Click

    Dim hCrypt As IntPtr
    Dim hSecretHash, hUserHash As IntPtr
    Dim hSecretKey As IntPtr
    Dim success As Boolean


    If CryptAcquireContext(hCrypt, vbNullString, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT) Then

        'create hash
        success = CryptCreateHash(hCrypt, CALG_MD5, 0, 0, hSecretHash)

        'hash stage 1
        success = CryptHashData(hSecretHash, Encoding.ASCII.GetBytes("yyyyyy"), "xxxxxx".length, 0)
        success = CryptHashData(hSecretHash, Encoding.ASCII.GetBytes("yyyyyy"), "yyyyyy".length, 0)

        'derive key
        success = CryptDeriveKey(hCrypt, CALG_RC4, hSecretHash, 0, hSecretKey)

        Dim newb(127) As Byte
        Dim teststring As String = "Testing"    
        Dim testbytes() As Byte = Encoding.ASCII.GetBytes(teststring)   
        Buffer.BlockCopy(testbytes, 0, newb, 0, testbytes.Length)

    Dim inputlength As UShort = Convert.ToUInt16(testbytes.Length)
        Dim newblength As UShort = CUShort(newb.Length)
        Dim bufferlength As UShort = newblength


    '---------------BOTH THESE FAIL (all above OK)
        success = CryptEncrypt(hSecretKey, 0, True, 0, newb, newblength, inputlength)
        success = CryptDecrypt(hSecretKey, 0, True, 0, newb, newblength)
    '--------------------------------------------


        'Destroy the user keycode
        CryptDestroyHash(hUserHash)

        'Destroy the secret key
        CryptDestroyKey(hSecretKey)
        CryptDestroyHash(hSecretHash)

        'Release the provider
        CryptReleaseContext(hCrypt, 0)

    End If

End Sub

Public Const ALG_CLASS_DATA_ENCRYPT As Int32 = 24576
Public Const ALG_CLASS_HASH As Int32 = 32768
Public Const ALG_TYPE_ANY As Int32 = 0
Public Const ALG_SID_RC4 As Int32 = 1
Public Const ALG_SID_RC2 As Int32 = 2
Public Const ALG_SID_MD5 As Int32 = 3
Public Const ALG_SID_SHA1 As Int32 = 4
Public Const ALG_SID_MAC As Int32 = 5
Public Const ALG_SID_HMAC As Int32 = 9
Public Const ALG_TYPE_BLOCK As Int32 = 1536
Public Const ALG_TYPE_STREAM As Int32 = 2048

Public Const CALG_MD5 As Int32 = ALG_CLASS_HASH + ALG_TYPE_ANY + ALG_SID_MD5
Public Const CALG_RC2 As Int32 = ALG_CLASS_DATA_ENCRYPT + ALG_TYPE_BLOCK + ALG_SID_RC2
Public Const CALG_RC4 As Int32 = ALG_CLASS_DATA_ENCRYPT + ALG_TYPE_STREAM + ALG_SID_RC4
Public Const CALG_SHA1 As Int32 = ALG_CLASS_HASH + ALG_TYPE_ANY + ALG_SID_SHA1
Public Const CALG_MAC As Int32 = ALG_CLASS_HASH + ALG_TYPE_ANY + ALG_SID_MAC
Public Const CALG_HMAC As Int32 = ALG_CLASS_HASH + ALG_TYPE_ANY + ALG_SID_HMAC

Public Const PROV_RSA_FULL As Int32 = &H1
Public Const CRYPT_VERIFYCONTEXT As Int32 = &HF0000000

Public Const HP_ALGID As Int32 = 1
Public Const HP_HASHVAL As Int32 = 2
Public Const HP_HASHSIZE As Int32 = 4
Public Const HP_HMAC_INFO As Int32 = 5

Public Const MS_DEF_PROV As String = "Microsoft Base Cryptographic Provider v1.0"

'Imported Functions:
<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

<DllImport("advapi32.dll", SetLastError:=True)>
    Public Shared Function CryptEncrypt( _
        ByVal hKey As IntPtr, _
        ByVal hHash As IntPtr, _
        ByVal Final As Boolean, _
        ByVal dwFlags As UShort, _
        pbData() As Byte, _
        pdwDataLen As UShort, _
        ByVal dwBufLen As UShort) As Boolean
    End Function

<DllImport("advapi32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)>
    Public Shared Function CryptDecrypt( _
        ByVal hKey As IntPtr, _
        ByVal hHash As IntPtr, _
        ByVal Final As Boolean, _
        ByVal dwFlags As UShort, _
        pbData() As Byte, _
        pdwDataLen As UShort _
    ) As Boolean
    End Function

<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

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

<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

<DllImport("advapi32.dll", setlasterror:=True)> _
    Public Shared Function CryptDeriveKey( _
        ByVal hProv As IntPtr, _
        ByVal Algid As Integer, _
        ByVal hBaseData As IntPtr, _
        ByVal dwflags As Integer, _
        ByRef phKey As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
    End Function

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

2 个答案:

答案 0 :(得分:0)

CryptEncrypt的Final参数是BOOL,它是一个32位的int。尝试将参数更改为Final为int32,或使用MarshalAs(UnmanagedType.Bool)

答案 1 :(得分:0)

可能是更多的事情,但立即ByVal dwFlags As UShort向我看。

msdn将该参数列为:

DWORD dwFlags,

DWORD是4个字节,因此是Int32或Integer(在VB.NET中)