如何使用 VBA 获取文件的 MD5 十六进制哈希?
Posted
技术标签:
【中文标题】如何使用 VBA 获取文件的 MD5 十六进制哈希?【英文标题】:How to get the MD5 hex hash for a file using VBA? 【发布时间】:2011-02-19 01:22:28 【问题描述】:我需要一个适用于文件的版本。
像这样简单的 Python 代码:
import hashlib
def md5_for_file(fileLocation, block_size=2**20):
f = open(fileLocation)
md5 = hashlib.md5()
while True:
data = f.read(block_size)
if not data:
break
md5.update(data)
f.close()
return md5.hexdigest()
但在 VBA 中。
【问题讨论】:
【参考方案1】:一个较老的问题,可以使用更好的答案。这些函数专门用于散列文件,而不是散列密码。作为奖励,我包含了一个 SHA1 函数。如果去掉类型声明,这些函数也可以在 VBScript 中工作,只是需要更改 GetFileBytes 函数以使用 FileSystemObject(或可能是 ADO Stream),因为 VBScript 中不存在 Free File。
Private Sub TestMD5()
Debug.Print FileToMD5Hex("C:\test.txt")
Debug.Print FileToSHA1Hex("C:\test.txt")
End Sub
Public Function FileToMD5Hex(sFileName As String) As String
Dim enc
Dim bytes
Dim outstr As String
Dim pos As Integer
Set enc = CreateObject("System.Security.Cryptography.MD5CryptoServiceProvider")
'Convert the string to a byte array and hash it
bytes = GetFileBytes(sFileName)
bytes = enc.ComputeHash_2((bytes))
'Convert the byte array to a hex string
For pos = 1 To LenB(bytes)
outstr = outstr & LCase(Right("0" & Hex(AscB(MidB(bytes, pos, 1))), 2))
Next
FileToMD5Hex = outstr
Set enc = Nothing
End Function
Public Function FileToSHA1Hex(sFileName As String) As String
Dim enc
Dim bytes
Dim outstr As String
Dim pos As Integer
Set enc = CreateObject("System.Security.Cryptography.SHA1CryptoServiceProvider")
'Convert the string to a byte array and hash it
bytes = GetFileBytes(sFileName)
bytes = enc.ComputeHash_2((bytes))
'Convert the byte array to a hex string
For pos = 1 To LenB(bytes)
outstr = outstr & LCase(Right("0" & Hex(AscB(MidB(bytes, pos, 1))), 2))
Next
FileToSHA1Hex = outstr 'Returns a 40 byte/character hex string
Set enc = Nothing
End Function
Private Function GetFileBytes(ByVal path As String) As Byte()
Dim lngFileNum As Long
Dim bytRtnVal() As Byte
lngFileNum = FreeFile
If LenB(Dir(path)) Then ''// Does file exist?
Open path For Binary Access Read As lngFileNum
ReDim bytRtnVal(LOF(lngFileNum) - 1&) As Byte
Get lngFileNum, , bytRtnVal
Close lngFileNum
Else
Err.Raise 53
End If
GetFileBytes = bytRtnVal
Erase bytRtnVal
End Function
【讨论】:
快速问题:UTF8Encoding 的变量“asc”没有在任何地方使用,这有什么用吗?此外,要使其与 VBScript 一起使用,您可能必须使用 ADODB.Stream 对象而不是 FreeFile 方法打开文件......无论如何,很好的分享! 我认为“asc”的东西一定是我使用这段代码散列密码时的产物。我现在已经删除了。是的,VBScript 中不存在免费文件。我确实找到了一个我认为可以使用文件系统对象的函数:***.com/questions/6060529/… 很好的解决方案,有几个尼特可供选择...Dim bytes() As Byte
提供了一点好处;并通过引用将其传递给重新配置的Private Sub GetFileBytes(sFileName As String, arrBytes() As Byte)
意味着您回避了冗余内存分配 - 对于资源使用和性能而言,这是一个真正的增益。房间里的大象是,对于非常大的文件,ReDim bytRtnVal(LOF(lngFileNum) - 1&) As Byte
会引发错误。但我不能发布更好的东西,因为我不知道 System.Security.Cryptography 函数中有任何“分块”或流式 API。
更新:用户 Florent B. 在this *** answer 中发布了一个答案,其中数据以块的形式传递给 MD5 哈希服务【参考方案2】:
应该这样做:
Dim fileBytes() As Byte = File.ReadAllBytes(path:=fullPath)
Dim Md5 As New MD5CryptoServiceProvider()
Dim byteHash() As Byte = Md5.ComputeHash(fileBytes)
Return Convert.ToBase64String(byteHash)
【讨论】:
嗯?首先,这是 VB.NET 而不是 VBA,其次,您省略了一些非常重要的导入命令。 糟糕,我将 VBA 误读为 VB.NET。 VBA 会更难一些,因为它没有使上述代码如此简单的所有 .NET 框架支持。至于导入,Visual Studio 可能会自动为您推荐这些,但为了完整起见,它们是 System.IO 和 System.Security.Cryptography。以上是关于如何使用 VBA 获取文件的 MD5 十六进制哈希?的主要内容,如果未能解决你的问题,请参考以下文章