2011-05-26 99 views
0

我正在使用以下函数为SQL备份文件生成MD5 \ SH1哈希。 这工作得很好,有进展报告等,但如果使用大型文件很慢。生成MD5和SHA1

我可以在SH1的同一时间生成MD5,而不必两次处理文件,使用时间加倍吗?将MD5结果转换为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 

以下是我如何使用上面生成一个散列:

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 
+0

出于好奇,你为什么要两个哈希函数? SHA不够用吗?而且你不能将MD5转换成SHA,反之亦然。 – 2011-05-26 12:27:00

+0

这两个值都会生成并传递给使用MD5或SHA来验证备份的客户端。在理想的世界里,他们都会用一种方法! – madlan 2011-05-26 12:30:53

回答

1

ToString方法可以创建大型字符串巨大的开销,因为级联是昂贵的(它创建大的临时缓存)和你经常这样做。改用StringBuilder(用正确尺寸初始化)。