Uso de la biblioteca MS Crypto en el servidor 2012 - Código de error CryptCreateHash 87: ERROR_INVALID_PARAMETER
Estoy intentando alojar una aplicación web en un nuevo entorno de Windows Server 2012, sin embargo, estoy recibiendo un error no declarado. Este código ha existido en nuestro código base durante años y no se han experimentado problemas en ninguna otra plataforma.
El código en cuestión llama a la función CryptCreateHash de advapi32.dll, una biblioteca de criptografía de Microsoft. Cuando se llama a la función, se me devuelve un 0 para indicar que la llamada falló, posteriormente Err.LastDllError devuelve el código de error 87, que es ERROR_INVALID_PARAMETER.
Como dije antes, este código ha funcionado perfectamente durante muchos años en una variedad de entornos, incluida una máquina de prueba de Windows Server 2012 utilizada por los Desarrolladores. Sin embargo, cuando se coloca en el entorno real que también ejecuta Server 2012 (aunque en un contexto un poco más complejo de un sistema de carga equilibrada) recibo el error. Ninguno de los servidores ha sido actualizado a Windows Server 2012 R2, está ejecutando la versión lista para usar del sistema operativo.
Después de crear un identificador para el proveedor de cripta utilizando:
CryptAcquireContext(hCryptProv, vbNullString, SERVICE_PROVIDER, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)
Uso hCryptProv para llamar a la función 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
Algunos ejemplos de los datos que se pasan al método desde los entornos en vivo y de desarrollo:
Dev:
hCryptProv = 4966968
CALG_MD5 = 32771
hHash = 0
Vivir:
hCryptProv = 1587622576
CALG_MD5 = 32771
hHash = 0
Parece que ambos conjuntos de parámetros son básicamente idénticos, aunque hCryptProv del servidor tiende a ser un número mucho mayor (posiblemente porque tiene mucha más RAM).
Intenté usar SHA1 en lugar de MD5 pero ocurrió el mismo error.
Posiblemente este es un problema relacionado con 32/64 bits, ¿se supone que advapi32.dll es de 32 bits?
Cualquier sugerencia sería apreciada, gracias.
EDITAR:
Prototipos según lo 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
He estado jugando con el tipo de datos dephProv
, previosuly era Integer, todavía tengo que probar usando IntPtr. He intentado usar ULong porque así es comoHCRYPTPROV
el tipo de datos se define en los documentos de MSDN.
typedef ULONG_PTR HCRYPTPROV;
También aquí están los valores del identificador devuelto por CryptAcquireContext en varias configuraciones:
LIVE 32: hCryptProv = 606412672
LIVE 64: hCryptProv = -1480179632
LOCAL: hCryptProv = 4966968
DEV 32: hCryptProv = 99009648
DEV 64: hCryptProv = 918798256
Esto es de cuando usé Integer como el tipo de datos, tenga en cuenta el desbordamiento en vivo.
Editar 2
Esto posiblemente es fijo. Ahora cuando llamo a CryptDecrypt recibo el error -2146893820 (NTE_BAD_LEN). posiblemente hacer con el*pdwDataLen
variable.
Aquí está la definición del 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
Y la llamada:
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