【问题标题】:How to get the MD5 hex hash for a file using VBA?如何使用 VBA 获取文件的 MD5 十六进制哈希?
【发布时间】:2011-02-19 01:22:28
【问题描述】:

如何使用 VBA 获取文件的 MD5 十六进制哈希?

我需要一个适用于文件的版本。

像这样简单的 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 中。

【问题讨论】:

    标签: vba hash md5 hex powerpoint


    【解决方案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 中不存在免费文件。我确实找到了一个我认为可以使用文件系统对象的函数:stackoverflow.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 StackOverflow 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。
    猜你喜欢
    • 1970-01-01
    • 2011-10-25
    • 1970-01-01
    • 2020-05-27
    • 2014-07-24
    • 2012-09-18
    • 2011-03-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多