新しい Windows Server 2012 環境で Web アプリケーションをホストしようとしていますが、予期しないエラーが発生します。このコードは何年も前からコードベースに存在しており、他のプラットフォームでは問題は発生していません。
問題のコードは、Microsoft の暗号化ライブラリである advapi32.dll の CryptCreateHash 関数を呼び出します。関数を呼び出すと、呼び出しが失敗したことを示す 0 が返され、その後、Err.LastDllError がエラー コード 87 (ERROR_INVALID_PARAMETER) を返します。
前に述べたように、このコードは、開発者が使用した Windows Server 2012 テスト マシンを含め、さまざまな環境で長年にわたって完全に機能しました。ただし、サーバー 2012 も実行しているライブ環境に置くと (負荷分散システムのもう少し複雑なコンテキストではありますが)、エラーが発生します。どちらのサーバーもまだ Windows Server 2012 R2 に更新されておらず、すぐに使えるバージョンの OS を実行しています。
以下を使用して 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 がはるかに多いためでしょうか?)。
MD5 の代わりに SHA1 を使用しようとしましたが、同じエラーが発生しました。
advapi32.dll が 32 ビットであると仮定すると、これは 32/64 ビット関連の問題である可能性がありますか?
任意の提案をいただければ幸いです、ありがとう。
編集:
要求に応じたプロトタイプ:
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 を使用してまだテストしていません。HCRYPTPROVMSDNドキュメントでデータ型が定義されているため、ULongを使用してみました。
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 <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