Использование криптографической библиотеки MS на сервере 2012 - код ошибки CryptCreateHash 87: ERROR_INVALID_PARAMETER
Я пытаюсь разместить веб-приложение в новой среде Windows Server 2012, однако получаю непредвиденную ошибку. Этот код существует в нашей кодовой базе в течение многих лет, и на любой другой платформе проблем не было.
Данный код вызывает функцию CryptCreateHash в advapi32.dll - криптографической библиотеке Microsoft. При вызове функции мне возвращается 0 для обозначения сбоя вызова, впоследствии Err.LastDllError возвращает код ошибки 87, который равен ERROR_INVALID_PARAMETER.
Как я уже говорил, этот код отлично работал в течение многих лет в различных средах, в том числе на тестовой машине Windows Server 2012, используемой разработчиками. Однако, когда я включаю живую среду, в которой также работает Server 2012 (хотя и в несколько более сложном контексте системы с балансировкой нагрузки), я получаю сообщение об ошибке. Ни один из серверов еще не был обновлен до Windows Server 2012 R2, на нем установлена готовая версия ОС.
После создания дескриптора для провайдера Crypt с помощью:
CryptAcquireContext(hCryptProv, vbNullString, SERVICE_PROVIDER, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)
Я использую hCryptProv для вызова функции 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
Некоторые примеры данных, передаваемых в метод из реальной и разработанной среды:
Dev:
hCryptProv = 4966968
CALG_MD5 = 32771
hHash = 0
Жить:
hCryptProv = 1587622576
CALG_MD5 = 32771
hHash = 0
Похоже, что оба эти набора параметров в основном идентичны, хотя серверs hCryptProv имеет тенденцию быть намного большим числом (возможно, потому что у этого есть намного больше RAM?).
Я попытался использовать SHA1 вместо MD5, но произошла та же ошибка.
Возможно, это проблема 32/64 бит, предполагая, что advapi32.dll является 32-битной?
Любые предложения будут оценены, спасибо.
РЕДАКТИРОВАТЬ:
Прототипы по запросу:
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
Я играл с типом данныхphProv
Ранее это было Integer, я еще не тестировал с помощью IntPtr. Я пытался использовать ULong, потому что это какHCRYPTPROV
тип данных определен в документах MSDN.
typedef ULONG_PTR HCRYPTPROV;
Также вот значения дескриптора, возвращаемого CryptAcquireContext в различных конфигурациях:
LIVE 32: hCryptProv = 606412672
LIVE 64: hCryptProv = -1480179632
LOCAL: hCryptProv = 4966968
DEV 32: hCryptProv = 99009648
DEV 64: hCryptProv = 918798256
Это когда я использовал Integer в качестве типа данных, обратите внимание на переполнение в реальном времени.
РЕДАКТИРОВАТЬ 2
Это возможно исправлено. Теперь, когда я вызываю CryptDecrypt, я получаю ошибку -2146893820 (NTE_BAD_LEN). возможно, делать с*pdwDataLen
переменная.
Вот определение метода:
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 Boolean
End Function
И звонок:
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