Usando a biblioteca de criptografia do MS no servidor 2012 - CryptCreateHash error code 87: ERROR_INVALID_PARAMETER
Eu estou tentando hospedar um aplicativo da web em um novo ambiente de servidor do Windows 2012, no entanto, estou recebendo um erro não-reconhecido. Este código existe em nossa base de código há anos e não houve problemas em nenhuma outra plataforma.
O código em questão chama a função CryptCreateHash de advapi32.dll - uma biblioteca de criptografia da Microsoft. Ao chamar a função, retornei um 0 para indicar que a chamada falhou; subsequentemente, Err.LastDllError retorna o código de erro 87, que é ERROR_INVALID_PARAMETER.
Como eu disse antes, esse código funcionou perfeitamente por muitos anos em vários ambientes - incluindo uma máquina de teste do Windows Server 2012 usada pelos desenvolvedores. No entanto, quando colocado no ambiente ao vivo, que também executa o Server 2012 (embora em um contexto um pouco mais complexo de um sistema de carga balanceada), recebo o erro. Nenhum servidor foi atualizado para o Windows Server 2012 R2, ele está executando a versão pronta para uso do sistema operacional.
Depois de criar um identificador para o Crypt Provider usando:
CryptAcquireContext(hCryptProv, vbNullString, SERVICE_PROVIDER, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)
Eu uso hCryptProv para chamar a função 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
Alguns exemplos dos dados que estão sendo transmitidos para o método a partir de ambientes ao vivo e de desenvolvimento:
Dev:
hCryptProv = 4966968
CALG_MD5 = 32771
hHash = 0
Viver:
hCryptProv = 1587622576
CALG_MD5 = 32771
hHash = 0
Parece que ambos os conjuntos de parâmetros são basicamente idênticos, embora o hCryptProv do servidor tende a ser um número muito maior (possivelmente porque tem muito mais RAM?).
Eu tentei usar SHA1 em vez de MD5, mas o mesmo erro ocorreu.
Possivelmente, este é um problema relacionado com 32/64 bits, presumindo advapi32.dll é 32 bits?
Qualquer sugestão seria apreciada, obrigado.
EDITAR:
Protótipos conforme solicitado:
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
Eu tenho jogado com o tipo de dados dephProv
, previosuly foi Integer, ainda estou para testar usando IntPtr. Eu tentei usar ULong porque é assim que oHCRYPTPROV
tipo de dados é definido na documentação do MSDN.
typedef ULONG_PTR HCRYPTPROV;
Também aqui estão os valores do identificador retornado por CryptAcquireContext em várias configurações:
LIVE 32: hCryptProv = 606412672
LIVE 64: hCryptProv = -1480179632
LOCAL: hCryptProv = 4966968
DEV 32: hCryptProv = 99009648
DEV 64: hCryptProv = 918798256
Isto é a partir de quando eu usei Integer como o tipo de dados, observe o estouro ao vivo.
EDIT 2
Isso possivelmente é fixo. Agora, quando eu chamo CryptDecrypt, recebo o erro -2146893820 (NTE_BAD_LEN). possivelmente a ver com o*pdwDataLen
variável.
Aqui está a definição do método:
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
E a chamada:
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