Używanie biblioteki kryptograficznej MS na serwerze 2012 - kod błędu CryptCreateHash 87: ERROR_INVALID_PARAMETER

Próbuję hostować aplikację internetową na nowym środowisku serwera Windows 2012, ale otrzymuję nieprzewidziany błąd. Ten kod istnieje w naszym kodzie źródłowym od lat i nie ma żadnych problemów na żadnej innej platformie.

Kod ten wywołuje funkcję CryptCreateHash w advapi32.dll - bibliotece kryptograficznej Microsoft. Podczas wywoływania funkcji zwracane jest 0, co oznacza, że ​​wywołanie nie powiodło się, a następnie Err.LastDllError zwraca kod błędu 87, który jest ERROR_INVALID_PARAMETER.

Jak już wspomniałem, ten kod działał doskonale przez wiele lat w różnych środowiskach - w tym na maszynie testowej Windows Server 2012 używanej przez programistów. Jednak po umieszczeniu w aktywnym środowisku, w którym działa również Server 2012 (choć w nieco bardziej złożonym kontekście systemu równoważenia obciążenia) otrzymuję błąd. Ani serwer nie został jeszcze zaktualizowany do systemu Windows Server 2012 R2, ale działa wersja systemu operacyjnego, która nie jest dostępna od razu.

Po utworzeniu uchwytu dla dostawcy krypt za pomocą:

CryptAcquireContext(hCryptProv, vbNullString, SERVICE_PROVIDER, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)

Używam hCryptProv do wywoływania funkcji CryptCreateHas.

  If CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, hHash) = 0 Then
      Dim _error As Integer = Err.LastDllError
      Throw New CryptoException("Error during CryptCreateHash. Error Code: " & _error.ToString)
  End If

Przykład danych przekazywanych do metody zarówno ze środowiska na żywo, jak i ze środowiska dev:

Dev:
hCryptProv = 4966968
CALG_MD5 = 32771
hHash = 0

Relacja na żywo:
hCryptProv = 1587622576
CALG_MD5 = 32771
hHash = 0

Wygląda na to, że oba te zestawy parametrów są zasadniczo identyczne, chociaż hCryptProv serwera ma tendencję do bycia znacznie większą liczbą (prawdopodobnie dlatego, że ma znacznie więcej pamięci RAM?).

Próbowałem użyć SHA1 zamiast MD5, ale wystąpił ten sam błąd.

Prawdopodobnie jest to problem związany z 32/64 bitami, zakładając, że advapi32.dll jest 32-bitowy?

Wszelkie sugestie będą mile widziane, dzięki.

EDYTOWAĆ:

Prototypy na żądanie:

Private Declare Function CryptAcquireContext Lib "advapi32.dll" Alias "CryptAcquireContextA" _
    (ByRef phProv As IntPtr, _
     ByVal pszContainer As String, _
     ByVal pszProvider As String, _
     ByVal dwProvType As Integer, _
     ByVal dwFlags As Integer) As Integer


Private Declare Function CryptCreateHash Lib "advapi32.dll" _
    (ByVal hProv As IntPtr, _
     ByVal Algid As Integer, _
     ByVal hKey As Integer, _
     ByVal dwFlags As Integer, _
     ByRef phHash As Integer) As Integer

Bawiłem się typem danychphProv, poprzednio była to liczba całkowita, muszę jeszcze przetestować za pomocą IntPtr. Próbowałem użyć ULong, ponieważ tak właśnie wyglądaHCRYPTPROV typ danych jest zdefiniowany w dokumentach MSDN.

typedef ULONG_PTR HCRYPTPROV; 

Również tutaj są wartości uchwytu zwróconego przez CryptAcquireContext w różnych konfiguracjach:

LIVE 32: hCryptProv = 606412672 
LIVE 64: hCryptProv = -1480179632 
LOCAL: hCryptProv = 4966968 
DEV 32: hCryptProv = 99009648 
DEV 64: hCryptProv = 918798256 

To jest, gdy użyłem Integer jako typu danych, zwróć uwagę na przepełnienie na żywo.

EDYCJA 2

To prawdopodobnie zostało naprawione. Teraz, gdy zadzwonię do CryptDecrypt, otrzymuję błąd -2146893820 (NTE_BAD_LEN). prawdopodobnie z*pdwDataLen zmienna.

Oto definicja metody:

Private Declare Function CryptDecrypt Lib "advapi32.dll" _
                              (ByVal hKey As IntPtr, _
                              ByVal hHash As IntPtr, _
                              ByVal Final As Boolean, _
                              ByVal dwFlags As Integer, _
                              ByVal pbData As String, _
                              ByRef pdwDataLen As Integer) _
                            As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function

A połączenie:

lLength = Len(strData)
If CryptDecrypt(_hKey, 0, 1, 0, sTemp, lLength) = False Then
                Dim _error As Integer = Err.LastDllError
                Throw New CryptoException("Error during CryptDecrypt. Error Code: " & _error.ToString)
            End If

questionAnswers(1)

yourAnswerToTheQuestion