我正在尝试在新的 Windows Server 2012 环境中托管 Web 应用程序,但是我收到了一个意外错误。该代码已在我们的代码库中存在多年,并且在任何其他平台上都没有遇到任何问题。
有问题的代码调用 advapi32.dll 的 CryptCreateHash 函数 - 一个 Microsoft 加密库。调用函数时返回 0 表示调用失败,随后 Err.LastDllError 返回错误代码 87,即 ERROR_INVALID_PARAMETER。
正如我之前所说,这段代码已经在各种环境中完美运行多年——包括开发人员使用的 Windows Server 2012 测试机器。但是,当放在也运行 Server 2012 的实时环境中时(尽管在负载平衡系统的稍微复杂的环境中),我收到了错误。两台服务器都尚未更新到 Windows Server 2012 R2,它正在运行开箱即用的操作系统版本。
使用以下命令创建 Crypt Provider 的句柄后:
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
从实时环境和开发环境传递给方法的数据的一些示例:
开发:
hCryptProv = 4966968
CALG_MD5 = 32771
hHash = 0
直播:
hCryptProv = 1587622576
CALG_MD5 = 32771
hHash = 0
看起来这两组参数基本相同,尽管服务器的 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
,以前它是整数,我还没有使用 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
这是从我使用整数作为数据类型开始的,请注意实时溢出。
编辑 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 <MarshalAs(UnmanagedType.Bool)> 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