生成 MD5 和 SHA1 [英] Generate MD5 and SHA1

查看:30
本文介绍了生成 MD5 和 SHA1的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用以下函数为 SQL 备份文件生成 MD5\SH1 哈希.这很好用,有进度报告等,但如果使用大文件会很慢.

I'm using the below function to generate an MD5\SH1 hash for SQL backup files. This works well, has progress report etc but is slow if using large files.

我能否在生成 SH1 的同时生成 MD5 而不必处理文件两次,从而使所用时间加倍?将 MD5 结果转换为 SHA1 怎么样?

Could I generate the MD5 at the same time as SH1 rather than having to process the file twice, doubling the time taken? What about converting an MD5 result to SHA1?

Imports System
Imports System.IO
Imports System.Security.Cryptography
Imports System.Text


Public Class ASyncFileHashAlgorithm
Protected hashAlgorithm As HashAlgorithm
Protected m_hash As Byte()
Protected cancel As Boolean = False
Protected m_bufferSize As Integer = 4096
Public Delegate Sub FileHashingProgressHandler(ByVal sender As Object, _
                                     ByVal e As FileHashingProgressArgs)
Public Event FileHashingProgress As FileHashingProgressHandler

Public Sub New(ByVal hashAlgorithm As HashAlgorithm)
    Me.hashAlgorithm = hashAlgorithm
End Sub

Public Function ComputeHash(ByVal stream As Stream) As Byte()
    cancel = False
    m_hash = Nothing
    Dim _bufferSize As Integer = m_bufferSize
    ' this makes it impossible to change the buffer size while computing  
    Dim readAheadBuffer As Byte(), buffer As Byte()
    Dim readAheadBytesRead As Integer, bytesRead As Integer
    Dim size As Long, totalBytesRead As Long = 0

    size = stream.Length
    readAheadBuffer = New Byte(_bufferSize - 1) {}
    readAheadBytesRead = stream.Read(readAheadBuffer, 0, _
                                     readAheadBuffer.Length)

    totalBytesRead += readAheadBytesRead

    Do
        bytesRead = readAheadBytesRead
        buffer = readAheadBuffer

        readAheadBuffer = New Byte(_bufferSize - 1) {}
        readAheadBytesRead = stream.Read(readAheadBuffer, 0, _
                                         readAheadBuffer.Length)

        totalBytesRead += readAheadBytesRead

        If readAheadBytesRead = 0 Then
            hashAlgorithm.TransformFinalBlock(buffer, 0, bytesRead)
        Else
            hashAlgorithm.TransformBlock(buffer, 0, bytesRead, buffer, 0)
        End If

        RaiseEvent FileHashingProgress(Me, New _
                             FileHashingProgressArgs(totalBytesRead, size))
    Loop While readAheadBytesRead <> 0 AndAlso Not cancel

    If cancel Then
        Return InlineAssignHelper(m_hash, Nothing)
    End If

    Return InlineAssignHelper(m_hash, hashAlgorithm.Hash)
End Function

Public Property BufferSize() As Integer
    Get
        Return m_bufferSize
    End Get
    Set(ByVal value As Integer)
        m_bufferSize = value
    End Set
End Property

Public ReadOnly Property Hash() As Byte()
    Get
        Return m_hash
    End Get
End Property

'Public Sub Cancel()
'    cancel = True
'End Sub

Public Overrides Function ToString() As String
    Dim hex As String = ""
    For Each b As Byte In Hash
        hex += b.ToString("x2")
    Next

    Return hex
End Function
Private Shared Function InlineAssignHelper(Of T)(ByRef target As T, _
                                                 ByVal value As T) As T
    target = value
    Return value
End Function
End Class


Public Class FileHashingProgressArgs
Inherits EventArgs
Public Property TotalBytesRead() As Long
    Get
        Return m_TotalBytesRead
    End Get
    Set(ByVal value As Long)
        m_TotalBytesRead = Value
    End Set
End Property
Private m_TotalBytesRead As Long
Public Property Size() As Long
    Get
        Return m_Size
    End Get
    Set(ByVal value As Long)
        m_Size = Value
    End Set
End Property
Private m_Size As Long

Public Sub New(ByVal totalBytesRead__1 As Long, ByVal size__2 As Long)
    TotalBytesRead = totalBytesRead__1
    Size = size__2
End Sub
End Class

以下是我使用上述方法生成哈希的方法:

The following is how I'm generating a hash using the above:

Shared hasher As New ASyncFileHashAlgorithm(SHA1.Create())

Private Function Test(Byval (strFilePathAndName, as String)


Dim stream As IO.Stream = DirectCast(File.Open(strFilePathAndName, _
                                               FileMode.Open), Stream)

        AddHandler hasher.FileHashingProgress, _
                   AddressOf OnFileHashingProgress

        Dim t = New Thread(AddressOf hasher.ComputeHash)
        t.Start(stream)
        While t.IsAlive
            Application.DoEvents()
        End While


        'LblMD5.Text = hasher.ToString???
        LblSHA1.Text = hasher.ToString

        stream.Dispose()

End Sub

Public Sub OnFileHashingProgress(ByVal sender As Object, _
                                 ByVal e As FileHashingProgressArgs)

    SetControlPropertyValue(uxChildForm.ProgressBar, "Position", _
                            CInt(e.TotalBytesRead / e.Size * 100))

End Sub

推荐答案

你的 ToString 方法可能会为大字符串带来巨大的开销,因为连接很昂贵(它会创建大的临时缓冲区)并且你经常这样做.改用 StringBuilder(用正确的大小初始化).

You ToString method may create tremendous overhead for large strings since concatenation is expensive (it creates large temporary buffer) and you do it often. Use a StringBuilder (initialised with the correct size) instead.

这篇关于生成 MD5 和 SHA1的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆