2013-11-15 5 views
0

Любой помощи со следующим высоко оценил .....функции CryptEncrypt/CryptDecrypt WinAPI сбой при вызове из vb.net

У меня есть C++ кода я унаследованный который расшифровывает некоторые структуры/массивы байт; Я пытался написать тестовую программу на VB.net, которая точно имитирует подпрограмму расшифровки C++, используя те же функции, т.е. используя вызовы WinAPI Crypto; при тестировании CryptAcquireContext, CryptCreateHash, CryptHashData и CryptDeriveKey все успешны;

Однако функции CryptEncrypt и CryptDecrypt не работают с ошибкой Invalid Parameter, даже в самом простом сценарии;

(Мне известно о пространстве имен System.Security.Cryptography ... и я прибегну к этому ... но код C++ включает в себя структуры с объединениями, и для тестирования лучше было сначала попробовать маршрут WinAPI)

пример кода ниже ... Я на Win7x64 sp1, против 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 
+0

Почему вы не используете библиотеку mscore крипто это вне меня. Это буквально голова и хвосты лучше WinCrypt, если вы программируете .NET. Наследие нуждается в стороне, это хорошо, что вы, по крайней мере, понимаете, что это правильный ход. – WhozCraig

ответ

0

Окончательный параметр CryptEncrypt является BOOL, который представляет собой 32-разрядное внутр. Попробуйте изменить параметр на Final как int32 или использовать MarshalAs (UnmanagedType.Bool)

+0

без радости, небрежно; Я попробовал множество разных (по-видимому, возможных) подписей для CryptDecrypt/CryptEncrypt, в том числе предоставленных в p/invoke ... все к сожалению, к сожалению; спасибо за то, что посмотрели, все равно; – user1161274

+0

Последние два параметра вашего вызова CryptEncrypt() находятся в неправильном порядке, это должна быть длина данных, а затем длина буфера. – Johnfed

0

Может быть больше вещей, но сразу ByVal dwFlags As UShort смотрит на меня.

MSDN от списков, что параметр, как:

DWORD dwFlags, 

DWORD 4 байта, поэтому было бы Int32 или целое число (в VB.NET)