Binäre Datei hashen

30/05/2009 - 15:02 von Dominik Schmidt | Report spam
Hallo,

ich möchte den Hashwert von einer Datei generieren, am besten (aber nicht
unbedingt) ohne auf externe DLLs zuzugreifen. Dabei geht es mir um den MD5-
und SHA1-Hash.

Ich habe viele Implementationen für die Hash-Generierung gefunden, aber
alle erzeugen mir scheinbar einen falschen Wert - ich vergleiche ihn zum
Testen mit dem Ergebnis von Hashtab (Hashtool).

Ich habe in allen Fàllen die jeweilige Datei im Binarymodus eingelesen und
vom Ergebnis dann mit der jeweilgen Routine den Hash berechnen lassen.
Wenn ich dies mit einer Textdatei mache, funktioniert es auch - nur bei
einer binàren Datei, z.B. einer Bilddatei, kommt ein falscher Hash-Wert
heraus.

Wo ist der Fehler?
Habe ich einen Denkfehler gemacht?
Warum funktionieren die Hashroutinen nur bei (eingelesenen) Textdateien?

Für die SHA1-Berechnung habe ich zum Beispiel diesen Code benutzt:
http://www.planet-source-code.com/v...p;lngWId=1
Für MD5 zum Beispiel den hier:
http://www.planet-source-code.com/v...p;lngWId=1
 

Lesen sie die antworten

#1 Dominik Schmidt
30/05/2009 - 17:24 | Warnen spam
Ok, hat sich erledigt, offensichtlich haben die von mir benutzten
Hashroutinen nicht korrekt gearbeitet und deshalb einen falschen Hash
ausgegeben.
Ich habe nun eine Routine gefunden, die fehlerfrei arbeitet und dazu noch
MD2, MD4, MD5 und SHA1 ausrechnen kann.
Da ich erstens nicht mehr weiß, wo ich sie gefunden habe und zweitens das
Original nur Dateien einlesen konnte, statt Strings zu verarbeiten, was ich
jetzt abgeàndert habe (Beispielaufruf mit Datei in Command1_Click), hier
der Code:

==
Option Explicit

Private Declare Function CryptAcquireContext Lib "advapi32.dll" _
Alias "CryptAcquireContextA" ( _
ByRef phProv As Long, _
ByVal pszContainer As String, _
ByVal pszProvider As String, _
ByVal dwProvType As Long, _
ByVal dwFlags As Long) As Long

Private Declare Function CryptReleaseContext Lib "advapi32.dll" ( _
ByVal hProv As Long, _
ByVal dwFlags As Long) As Long

Private Declare Function CryptCreateHash Lib "advapi32.dll" ( _
ByVal hProv As Long, _
ByVal Algid As Long, _
ByVal hKey As Long, _
ByVal dwFlags As Long, _
ByRef phHash As Long) As Long

Private Declare Function CryptDestroyHash Lib "advapi32.dll" ( _
ByVal hHash As Long) As Long

Private Declare Function CryptHashData Lib "advapi32.dll" ( _
ByVal hHash As Long, _
pbData As Byte, _
ByVal dwDataLen As Long, _
ByVal dwFlags As Long) As Long

Private Declare Function CryptGetHashParam Lib "advapi32.dll" ( _
ByVal hHash As Long, _
ByVal dwParam As Long, _
pbData As Any, _
pdwDataLen As Long, _
ByVal dwFlags As Long) As Long

Private Const PROV_RSA_FULL = 1

Private Const CRYPT_NEWKEYSET = &H8

Private Const ALG_CLASS_HASH = 32768

Private Const ALG_TYPE_ANY = 0

Private Const ALG_SID_MD2 = 1
Private Const ALG_SID_MD4 = 2
Private Const ALG_SID_MD5 = 3
Private Const ALG_SID_SHA1 = 4

Enum HashAlgorithm
MD2 = ALG_CLASS_HASH Or ALG_TYPE_ANY Or ALG_SID_MD2
MD4 = ALG_CLASS_HASH Or ALG_TYPE_ANY Or ALG_SID_MD4
MD5 = ALG_CLASS_HASH Or ALG_TYPE_ANY Or ALG_SID_MD5
SHA1 = ALG_CLASS_HASH Or ALG_TYPE_ANY Or ALG_SID_SHA1
End Enum

Private Const HP_HASHVAL = 2
Private Const HP_HASHSIZE = 4

Public Function HashText( _
ByVal Text As String, _
Optional ByVal Algorithm As HashAlgorithm = MD5) As String
Dim hCtx As Long
Dim hHash As Long
Dim lFile As Long
Dim lRes As Long
Dim lLen As Long
Dim lIdx As Long
Dim abHash() As Byte
Dim i

' Get default provider context handle
lRes = CryptAcquireContext(hCtx, vbNullString, _
vbNullString, PROV_RSA_FULL, 0)

If lRes = 0 And Err.LastDllError = &H80090016 Then

' There's no default keyset container!!!
' Get the provider context and create
' a default keyset container
lRes = CryptAcquireContext(hCtx, vbNullString, _
vbNullString, PROV_RSA_FULL, CRYPT_NEWKEYSET)
End If

If lRes <> 0 Then

' Create the hash
lRes = CryptCreateHash(hCtx, Algorithm, 0, 0, hHash)

If lRes <> 0 Then

If Err.Number = 0 Then

Const BLOCK_SIZE As Long = 32 * 1024& ' 32K
ReDim abblock(1 To BLOCK_SIZE) As Byte
Dim lCount As Long
Dim lBlocks As Long
Dim lLastBlock As Long

' Calculate how many full blocks
' the string contains
lBlocks = Len(Text) \ BLOCK_SIZE

' Calculate the remaining data length
lLastBlock = Len(Text) - lBlocks * BLOCK_SIZE

' Hash the blocks
For lCount = 1 To lBlocks


' Add the chunk to the hash
lRes = CryptHashData(hHash, abblock(1), BLOCK_SIZE, 0)

' Stop the loop if CryptHashData fails
If lRes = 0 Then Exit For

Next

' Is there more data?
If lLastBlock > 0 And lRes <> 0 Then

' Get the last block
ReDim abblock(1 To lLastBlock) As Byte
For i = 1 To lLastBlock
abblock(i) = Asc(Mid(Text, i, 1))
Next i

' Hash the last block
lRes = CryptHashData(hHash, abblock(1), lLastBlock, 0)

End If


End If

If lRes <> 0 Then

' Get the hash lenght
lRes = CryptGetHashParam(hHash, HP_HASHSIZE, lLen, 4, 0)

If lRes <> 0 Then

' Initialize the buffer
ReDim abHash(0 To lLen - 1)

' Get the hash value
lRes = CryptGetHashParam(hHash, HP_HASHVAL, abHash(0), lLen,
0)

If lRes <> 0 Then

' Convert value to hex string
For lIdx = 0 To UBound(abHash)
HashText = HashText & _
Right$("0" & Hex$(abHash(lIdx)), 2)
Next

End If

End If

End If

' Release the hash handle
CryptDestroyHash hHash

End If

End If

' Release the provider context
CryptReleaseContext hCtx, 0

' Raise an error if lRes = 0
If lRes = 0 Then Err.Raise Err.LastDllError

End Function

Private Sub Command1_Click()
Dim fno
Dim Buffer As String

fno = FreeFile
Open "C:\BILD.jpg" For Binary As #fno
Buffer = String$(LOF(fno), " ")
Get #fno, , Buffer
Close #fno

MsgBox HashText(Buffer, SHA1)
End Sub

Ähnliche fragen