1

新しい 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
4

1 に答える 1

3

type がある場合は、.NET のULONG_PTRように定義する必要があります。IntPtrDllImportAttribute も必要です。次のようにする必要がありCryptCreateHashます。

Declare Auto Function CryptCreateHash Lib "advapi32.dll" _
    (ByVal hProv As IntPtr, _
     ByVal algId As Integer, _
     ByVal hKey As IntPtr, _
     ByVal dwFlags As Integer, _
     ByRef phHast As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean

また、最後のエラーを設定するように指示したことを確認してください。C# では、DllImportAttributeを使用して、SetLastError=true. それ以外の場合、呼び出しMarshal.GetLastWin32Errorは期待されるものを返しません。

アップデート

プロトタイプCryptDecryptは次のようになります。

Declare Function CryptDecrypt Lib "advapi32.dll" 
    (ByVal hkey As IntPtr, _
     ByVal hHash As IntPtr, _
     <MarshalAs(UnmanagedType.Bool)> ByVal final As Boolean, _
     ByVal flags As Integer, _
     ByVal data As Byte(), 
     ByRef dataLen As Integer) As <MarshalAs(UnmanagedType.Bool)> Boolean

文字列をバイト配列に変換する必要があります。dataLenまた、パラメーターは、文字列の長さではなく、バイト バッファーの長さであることに注意してください。

ほとんどの Windows API 呼び出しのプロトタイプと例を管理しているpinvoke.netをチェックしてください。

于 2013-12-12T18:32:32.600 に答える