Results 1 to 3 of 3

Thread: Crypto API giving me unexplained problems.

  1. #1

    Thread Starter
    Frenzied Member
    Join Date
    Oct 2008
    Posts
    1,181

    Crypto API giving me unexplained problems.

    Ok, so I have this program, just to test my ability to get the Crypto API started, and closed properly. And I'm already having troubles.

    Here's my test code.
    Code:
    Private Declare Function CryptAcquireContext Lib "advapi32.dll" Alias "CryptAcquireContextA" (ByRef phProv As Long, ByVal pszContainer As String, ByVal pszProvider As String, ByVal dwProvType As Long, ByVal dwFlags As Long) As Long
    Private Declare Function CryptReleaseContext Lib "advapi32.dll" (ByRef hProv As Long, ByRef dwFlags As Long) As Long
    Private Const PROV_RSA_FULL As Long = &H1
    Private Const CRYPT_VERIFYCONTEXT As Long = &HF0000000
    
    Private Sub Form_Load()
    Dim hProv As Long
    Dim RetVal As Long
    
    RetVal = CryptAcquireContext(hProv, vbNullString, "Microsoft Base Cryptographic Provider v1.0", PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)
    If RetVal = 0 Then Print "CryptAcquireContext Error: " & CStr(GetLastError)
    
    Print "Crypto Provider Handle: " & CStr(hProv)
    
    RetVal = CryptReleaseContext(hProv, 0)
    If RetVal = 0 Then Print "CryptReleaseContext Error: " & CStr(GetLastError)
    End Sub
    Here's what I'm seeing when running the program.




    If there is any error, it should be first relating to CryptAcquireContext, which results in an invalid Crypto Provider Handle (the value 0), which then results in another error when using that handle with CryptReleaseContext. What's happening is the program works PERFECTLY up to the part where there it tries to release that handle, and only THEN there is an error. Releasing something should not be the first time an error appears, since it IS a valid crypto handle, and it's being used for NOTHING ELSE. Therefore it shouldn't be a situation where it can't release it due to it using it for something else.

    And the error it generates (error 87) corresponds to the error handle ERROR_INVALID_PARAMETER. This means that one of the parameters I gave it is incorrect. How can it be incorrect. The hProv (Provider Handle) is valid, as it was generated by CryptAcquireContext. And the other parameter for CryptReleaseContext (dwFlags) must be set to 0, as the MSDN page for the function says this about that parameter:
    Reserved for future use and must be zero. If dwFlags is not set to zero, this function returns FALSE but the CSP is released.
    So I don't see why my code is failing. And since it's failing in the most basic parts of the Crypto API, I fear I may not be able to use it. Anyone who can help me here, please do so.

  2. #2
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    8,598

    Re: Crypto API giving me unexplained problems.

    You may not be passing 0 to CryptReleaseContext's second parameter since you declared it ByRef. If you were passing a Long with a value of 0, the function would actually be receiving a value equivalent to the address of this Long. You passed 0 as a constant which I would guess is placed into a temporary variable by the VB6 runtime before calling the function hence you may not be passing 0 at all.

    Change CryptReleaseContext's second parameter to be passed by value.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  3. #3

    Thread Starter
    Frenzied Member
    Join Date
    Oct 2008
    Posts
    1,181

    Re: Crypto API giving me unexplained problems.

    Nevermind. The resource I was using to find the API declarations (API Viewer 2004) has a couple errors in its declaration. It's a 3rd party product that has a lot more functions listed than the official MS API Viewer that comes with VB6 (since there's a lot more API functions now than when VB6 was made). Unfortunately some of them are not correctly declared in this 3rd party software. By trial and error though, I managed to figure out what was wrong. A couple ByRef arguments should have been ByVal instead.

    Below is the complete code for my program I made that creates and displays the MD5 hash for the text "This is a test.". You can verify it is correct by typing "This is a test." into the online MD5 hash generating webpage http://md5-hash-online.waraxe.us/ and pressing the "Calculate md5 hash" button.

    Code:
    Private Declare Function CryptCreateHash Lib "advapi32.dll" (ByVal hProv As Long, ByVal Algid As Long, ByVal hKey As Long, ByVal dwFlags As Long, ByRef phHash As Long) As Long
    Private Declare Function CryptHashData Lib "advapi32.dll" (ByVal hHash As Long, ByRef pbData As Byte, ByVal dwDataLen As Long, ByVal dwFlags As Long) As Long
    Private Declare Function CryptDestroyHash Lib "advapi32.dll" (ByVal hHash As Long) As Long
    Private Declare Function CryptAcquireContext Lib "advapi32.dll" Alias "CryptAcquireContextA" (ByRef phProv As Long, ByVal pszContainer As String, ByVal pszProvider As String, ByVal dwProvType As Long, ByVal dwFlags As Long) As Long
    Private Declare Function CryptReleaseContext Lib "advapi32.dll" (ByVal hProv As Long, ByVal dwFlags As Long) As Long
    Private Declare Function CryptGetHashParam Lib "advapi32.dll" (ByVal hHash As Long, ByVal dwParam As Long, ByVal pByte As Long, ByRef pdwDataLen As Long, ByVal dwFlags As Long) As Long
    Private Declare Function GetLastError Lib "kernel32.dll" () As Long
    
    Private Const PROV_RSA_FULL As Long = &H1
    Private Const CRYPT_VERIFYCONTEXT As Long = &HF0000000
    Private Const HP_HASHSIZE As Long = &H4
    Private Const HP_HASHVAL As Long = &H2
    Private Const CALG_MD5 As Long = &H8003&
    
    Private Sub Form_Load()
    Dim hProv As Long
    Dim hHash As Long
    Dim RetVal As Long
    Dim DataLen As Long
    Dim DataIn() As Byte
    Dim HashLen As Long
    Dim HashOut() As Byte
    Dim n As Long
    
    DataIn() = StrConv("This is a test.", vbFromUnicode)
    DataLen = UBound(DataIn) + 1
    
    Form1.Show
    
    Print "Number of Characters in String: " & CStr(DataLen)
    Print "Text to Be Hashed: " & StrConv(DataIn, vbUnicode)
    
    RetVal = CryptAcquireContext(hProv, vbNullString, "Microsoft Base Cryptographic Provider v1.0", PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)
    If RetVal = 0 Then Print "CryptAcquireContext Error: " & CStr(GetLastError)
    
    Print "Crypto Provider Handle: " & CStr(hProv)
    
    RetVal = CryptCreateHash(hProv, CALG_MD5, 0, 0, hHash)
    If RetVal = 0 Then Print "CryptCreateHash Error: " & CStr(GetLastError)
    
    Print "Hash Handle: " & CStr(hHash)
    
    RetVal = CryptHashData(hHash, DataIn(0), DataLen, 0)
    If RetVal = 0 Then Print "CryptHashData Error: " & CStr(GetLastError)
    
    RetVal = CryptGetHashParam(hHash, HP_HASHSIZE, VarPtr(HashLen), 4, 0)
    If RetVal = 0 Then Print "CryptGetHashParam (HashSize) Error: " & CStr(GetLastError)
    
    Print "Number of Bytes in Hash: " & CStr(HashLen)
    ReDim HashOut(HashLen - 1)
    
    RetVal = CryptGetHashParam(hHash, HP_HASHVAL, VarPtr(HashOut(0)), HashLen, 0)
    If RetVal = 0 Then Print "CryptGetHashParam (HashValue) Error: " & CStr(GetLastError)
    
    Print "MD5 Hash: ";
    For n = 0 To HashLen - 1
        Print HexByte(HashOut(n));
    Next n
    Print ""
    
    RetVal = CryptDestroyHash(hHash)
    If RetVal = 0 Then Print "CryptDestroyHash Error: " & CStr(GetLastError)
    
    RetVal = CryptReleaseContext(hProv, 0)
    If RetVal = 0 Then Print "CryptReleaseContext Error: " & CStr(GetLastError)
    End Sub
    
    
    Private Function HexByte(ByVal Value As Byte) As String
    HexByte = String$(2 - Len(Hex$(Value)), "0") & Hex$(Value)
    End Function
    Last edited by Ben321; Aug 27th, 2014 at 03:16 AM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width