0

AdvApi32 の暗号関数を使用して、ユーザーが指定したデータ (ファイル) を MD5 ハッシュしようとしています。ファイルが非常に大きい場合 (数百 MB 以上) でない限り、すべて問題ありません。その場合、最終的に OutOfMemory 例外が発生します。

CryptHashData解決策は、同じものを使用してHashObject(たとえば)一度に4096バイトのみを処理するために繰り返し呼び出しを行うことであると考えました。

これは機能しているように見えますが、返されたハッシュは正しくありません。

Function HashFile(File As FolderItem) As String
  Declare Function CryptAcquireContextW Lib "AdvApi32" (ByRef provider as Integer, container as Integer, providerName as WString, _
  providerType as Integer, flags as Integer) as Boolean
  Declare Sub CryptDestroyHash Lib "AdvApi32" (hashHandle as Integer )
  Declare Function CryptCreateHash Lib "AdvApi32" (provider as Integer, algorithm as Integer, key as Integer, flags as Integer, _
  ByRef hashHandle as Integer) as Boolean
  Declare Function CryptHashData Lib "AdvApi32" (hashHandle as Integer, data as Ptr, length as Integer, flags as Integer) as Boolean
  Declare Function CryptGetHashParam Lib "AdvApi32" (hashHandle as Integer, type as Integer, value as Ptr, ByRef length as Integer, _
  flags as Integer) as Boolean

  Const HP_HASHVAL = &h0002
  Const HP_HASHSIZE = &h0004
  Const MS_DEF_PROV = "Microsoft Base Cryptographic Provider v1.0"
  Const PROV_RSA_FULL = 1
  Const CRYPT_NEWKEYSET = &h00000008
  Const CALG_MD5 = &h00008003

  Dim provider As Integer
  Dim hashHandle As Integer

  If Not CryptAcquireContextW(provider, 0, MS_DEF_PROV, PROV_RSA_FULL, 0) Then
    If Not CryptAcquireContextW(provider, 0, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_NEWKEYSET) Then
      Raise New RuntimeException
    End If
  End If

  If Not CryptCreateHash(provider, CALG_MD5, 0, 0, hashHandle) Then
    Raise New RuntimeException
  End If

  Dim dataPtr As New MemoryBlock(4096)
  Dim bs As BinaryStream
  bs = bs.Open(File)
  dataPtr.StringValue(0, 4096) = bs.Read(4096)

  Do
    If CryptHashData(hashHandle, dataPtr, dataPtr.Size, 0) Then
      dataPtr = New MemoryBlock(4096)
      dataPtr.StringValue(0, 4095) = bs.Read(4096)
    End If
  Loop Until bs.EOF

  Dim size as Integer = 4
  Dim toss As New MemoryBlock(4)
  If Not CryptGetHashParam(hashHandle, HP_HASHSIZE, toss, size, 0) Then
    Raise New RuntimeException
  End If

  size = toss.UInt32Value(0)

  Dim hashValue As New MemoryBlock(size)
  If Not CryptGetHashParam(hashHandle, HP_HASHVAL, hashValue, size, 0) Then
    Raise New RuntimeException
  End If
  CryptDestroyHash(hashHandle)

  //Convert binary to hex
  Dim hexvalue As Integer
  Dim hexedInt As String
  Dim src As String = hashValue.StringValue(0, hashValue.Size)
  For i As Integer = 1 To LenB(src)
    hexvalue = AscB(MidB(src, i, 1))
    hexedInt = hexedInt + RightB("00" + Hex(hexvalue), 2)
  next

  Return LeftB(hexedInt, LenB(hexedInt))

End Function

ここで何が間違っていますか?得られる出力は一貫していますが、間違っています。

4

2 に答える 2

0

C++でその msdn の例を確認しましたか? あなたの質問に対する非常によく似た答え。

于 2013-04-27T20:14:03.117 に答える