首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在非常大的输入上使用CryptHashData

在非常大的输入上使用CryptHashData
EN

Stack Overflow用户
提问于 2011-12-22 07:54:25
回答 2查看 1.9K关注 0票数 0

我正在尝试使用AdvApi32中的MD5函数对用户提供的数据(文件)进行加密。除非文件非常大(数百MB ),否则一切都很好。或更大),在这种情况下,我最终会得到一个OutOfMemory异常。

我认为解决方案应该是使用相同的HashObject重复调用CryptHashData,并且一次仅处理(例如) 4096字节。

这看起来是有效的,但是返回的散列是不正确的。

代码语言:javascript
复制
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

我在这里做错了什么?我得到的输出是一致的,但却是错误的。

EN

回答 2

Stack Overflow用户

发布于 2013-04-28 04:14:03

你在C++上查过that msdn example了吗?对你的问题的回答非常相似。

票数 0
EN

Stack Overflow用户

发布于 2013-04-28 05:01:32

我认为问题在于,由于您以4096字节的块读取数据-当数据不是4096的倍数时,您将包含不想要的尾随0或可能的垃圾值。在循环中尝试bs.Read(1)而不是bs.Read(4096)Loop Until bs.EOF,以便测试现在是否计算出正确的哈希值。如果成功,请调整您的循环以单独处理剩余的(%4096)字节。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8597893

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档