MD5



  • Hallo hat mal wer versucht den MD5 Alogrithmus nach zu bauen ?

    http://de.wikipedia.org/wiki/Message-Digest_Algorithm_5

    Und bringt der Pseudo Code hier was ??

    // Beachte: Alle Variablen sind vorzeichenlose 32 Bit-Werte und
    // verhalten sich bei Berechnungen kongruent (≡) modulo 2^32
    
    // Definiere r wie folgt:
    var int[64] r, k
    r[ 0..15] := {7, 12, 17, 22,  7, 12, 17, 22,  7, 12, 17, 22,  7, 12, 17, 22}
    r[16..31] := {5,  9, 14, 20,  5,  9, 14, 20,  5,  9, 14, 20,  5,  9, 14, 20}
    r[32..47] := {4, 11, 16, 23,  4, 11, 16, 23,  4, 11, 16, 23,  4, 11, 16, 23}
    r[48..63] := {6, 10, 15, 21,  6, 10, 15, 21,  6, 10, 15, 21,  6, 10, 15, 21}
    
    // Verwende den binären Vorkommateil vom 2^32-fachen Betrag des Sinus
    // von Integerwerten als Konstanten:
    für alle i von 0 bis 63
        k[i] := floor(abs(sin(i + 1)) × 2^32)
    
    // Initialisiere die Variablen: (lt. RFC 1321)
    var int h0 := 0x67452301
    var int h1 := 0xEFCDAB89
    var int h2 := 0x98BADCFE
    var int h3 := 0x10325476
    
    // Vorbereitung der Nachricht 'message':
    var int message_laenge := bit_length(message)
    erweitere message um bit "1"
    erweitere message um bits "0" bis Länge von message in bits ≡ 448 (mod 512)
    erweitere message um message_laenge als 64-Bit little-endian Integer
    
    // Verarbeite die Nachricht in aufeinander folgenden 512-Bit Blöcken:
    für alle 512-Bit Block von message
        unterteile Block in 16 32-bit little-endian Worte w(i), 0 ≤ i ≤ 15
    
        // Initialisiere den Hash-Wert für diesen Block:
        var int a := h0
        var int b := h1
        var int c := h2
        var int d := h3
    
        // Hauptschleife:
        für alle i von 0 bis 63
            wenn 0 ≤ i ≤ 15 dann
                f := (b and c) or ((not b) and d)
                g := i
            sonst wenn 16 ≤ i ≤ 31 dann
                f := (b and d) or (c and (not d))
                g := (5×i + 1) mod 16
            sonst wenn 32 ≤ i ≤ 47 dann
                f := b xor c xor d
                g := (3×i + 5) mod 16
            sonst wenn 48 ≤ i ≤ 63 dann
                f := c xor (b or (not d))
                g := (7×i) mod 16
            wenn_ende
    
            temp := d
            d := c
            c := b
            b := ((a + f + k(i) + w(g)) leftrotate r(i)) + b 
            a := temp
    
        // Addiere den Hash-Wert des Blocks zur Summe der vorherigen Hashes:
        h0 := h0 + a
        h1 := h1 + b
        h2 := h2 + c
        h3 := h3 + d
    
    var int digest := h0 append h1 append h2 append h3 //(Darstellung als little-endian)
    


  • Auf der Wiki-Seite gibt es doch auch einen Link mit C++ Beispielcode.



  • hab ihn nachgebaut und das kam raus:

    md5sum.cpp

    #include "md5sum.hpp"
    
    #include <sstream>
    #include <vector>
    
    #include <cmath>
    
    md5sum::md5sum(void)
    {
    	calculate_checksum("");
    }
    
    md5sum::md5sum(__in const std::string& data)
    {
    	calculate_checksum(data);
    }
    
    md5sum::md5sum(__in const BYTE *data, __in unsigned int len)
    {
    	calculate_checksum(data, len);
    }
    
    md5sum::md5sum(__in const std::ifstream& data)
    {
    	calculate_checksum(data);
    }
    
    void md5sum::calculate_checksum(__in const BYTE *data, __in unsigned int len)
    {
    	// Daten in korrektes Format bringen
    	const unsigned int length = len;
    	std::vector<BYTE> vData(length);
    	for (unsigned int n = 0; n < length; ++n)
    		vData[n] = data[n];
    	vData.push_back(128);
    	while ((vData.size() + 8) % 64)
    		vData.push_back(0);
    	unsigned __int64 iSizeInBits = length * 8;
    	BYTE *pLength = reinterpret_cast<BYTE*>(&iSizeInBits);
    	for (int n = 0; n < 8; ++n)
    		vData.push_back(pLength[n]);
    
    	// Konstanten definieren
    	h0 = 0x67452301;
    	h1 = 0xEFCDAB89;
    	h2 = 0x98BADCFE;
    	h3 = 0x10325476;
    	const DWORD r[64] =
    	{
    		7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
    		5,  9, 14, 20, 5,  9, 14, 20, 5,  9, 14, 20, 5,  9, 14, 20,
    		4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
    		6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21
    	};
    	DWORD k[64];
    	for (int n = 0; n < 64; ++n)
    		k[n] = static_cast<DWORD>(floor(abs(sin(static_cast<double>(n + 1))) * (pow(static_cast<double>(2), 32))));
    
    	// Aufteilung
    	unsigned __int64 iFullSize = static_cast<unsigned __int64>(vData.size());
    	unsigned __int64 iNumParts = iFullSize / 64;
    
    	// Verarbeitung
    	for (unsigned __int64 n = 0; n < iNumParts; ++n)
    	{
    		// Hash-Wert initialisieren
    		DWORD a = h0, b = h1, c = h2, d = h3;
    		DWORD f = 0, g = 0;
    
    		// in 16 32-Bit Worte unterteilen
    		union
    		{
    			BYTE bValues[64];
    			DWORD dwValues[16];
    		} Part;
    		for (int i = 0; i < 64; ++i)
    			Part.bValues[i] = vData[i + static_cast<int>(n * 64)];
    
    		// Hauptschleife
    		for (int i = 0; i < 64; ++i)
    		{
    			if ((i >= 0) && (i <= 15 ))
    			{
    				f = (b & c) | ((~b) & d);
    				g = i;
    			}
    			else if ((i >= 16) && (i <= 31))
    			{
    				f = (b & d) | (c & (~d));
    				g = ((5 * i) + 1) % 16;
    			}
    			else if ((i >= 32) && (i <= 47))
    			{
    				f = b ^ c ^ d;
    				g = ((3 * i) + 5) % 16;
    			}
    			else
    			{
    				f = c ^ (b | (~d));
    				g = (7 * i) % 16;
    			}
    
    			DWORD temp = d;
    			d = c;
    			c = b;
    			b = _lrotl((a + f + k[i] + Part.dwValues[g]), r[i]) + b;
    			a = temp;
    		}
    
    		// Hashwerte addieren
    		h0 += a;
    		h1 += b;
    		h2 += c;
    		h3 += d;
    	}
    }
    
    void md5sum::calculate_checksum(__in const std::string& data)
    {
    	md5sum::calculate_checksum(reinterpret_cast<const BYTE*>(data.c_str()), data.length());
    }
    
    void md5sum::calculate_checksum(__in const std::ifstream& data)
    {
    	std::ifstream &rData = const_cast<std::ifstream&>(data);
    	rData.seekg(0, std::ios::end);
    	unsigned int size = rData.tellg();
    	rData.seekg(0);
    	BYTE *pData = new BYTE[size];
    	rData.read(reinterpret_cast<char*>(pData), size);
    	rData.seekg(0);
    	calculate_checksum(pData, size);
    	delete[] pData;
    }
    
    std::string md5sum::digest(void)
    {
    	// Checksumme zusammensetzen
    	std::stringstream digest;
    	digest << std::hex;
    	union
    	{
    		BYTE bValues[4];
    		DWORD dwValue;
    	} h;
    	// DWord 1
    	h.dwValue = h0;
    	BYTE tmp = h.bValues[0];
    	h.bValues[0] = h.bValues[3];
    	h.bValues[3] = tmp;
    	tmp = h.bValues[1];
    	h.bValues[1] = h.bValues[2];
    	h.bValues[2] = tmp;
    	digest << h.dwValue;
    	// DWord 2
    	h.dwValue = h1;
    	tmp = h.bValues[0];
    	h.bValues[0] = h.bValues[3];
    	h.bValues[3] = tmp;
    	tmp = h.bValues[1];
    	h.bValues[1] = h.bValues[2];
    	h.bValues[2] = tmp;
    	digest << h.dwValue;
    	// DWord 3
    	h.dwValue = h2;
    	tmp = h.bValues[0];
    	h.bValues[0] = h.bValues[3];
    	h.bValues[3] = tmp;
    	tmp = h.bValues[1];
    	h.bValues[1] = h.bValues[2];
    	h.bValues[2] = tmp;
    	digest << h.dwValue;
    	// DWord 4
    	h.dwValue = h3;
    	tmp = h.bValues[0];
    	h.bValues[0] = h.bValues[3];
    	h.bValues[3] = tmp;
    	tmp = h.bValues[1];
    	h.bValues[1] = h.bValues[2];
    	h.bValues[2] = tmp;
    	digest << h.dwValue;
    
    	// Resultat zurückgeben
    	return digest.str();
    }
    

    md5sum.hpp

    #pragma once
    
    #include <Windows.h>
    
    #include <string>
    #include <fstream>
    
    class md5sum
    {
    private:
    	DWORD h0, h1, h2, h3;
    	void calculate_checksum(__in const BYTE *data, __in unsigned int len);
    	void calculate_checksum(__in const std::string& data);
    	void calculate_checksum(__in const std::ifstream& data);
    public:
    	md5sum(void);
    	md5sum(__in const BYTE *data, __in unsigned int len);
    	md5sum(__in const std::string& data);
    	md5sum(__in const std::ifstream& data);
    	std::string digest(void);
    };
    
    #define MD5(data) md5sum(data).digest().c_str()
    


  • und als kleines Beispielprog:

    #include <iostream>
    #include <fstream>
    
    #include "md5sum.hpp"
    
    int main(int argc, char** argv)
    {
    	std::cout << "md5sum Version 1.0" << std::endl;
    	std::cout << "Copyright (C) 2009, Drako" << std::endl;
    	std::cout << std::endl;
    
    	if (argc != 2)
    	{
    		std::cout << "Usage: md5sum [filename|string]" << std::endl;
    		return 0;
    	}
    
    	std::ifstream inFile(argv[1], std::ios::in | std::ios::binary);
    	if (!(inFile.is_open()))
    	{
    		std::cout << "String:   " << argv[1] << std::endl;
    		std::cout << "MD5 Hash: " << md5sum(argv[1]).digest() << std::endl;
    	}
    	else
    	{
    		std::cout << "Filename: " << argv[1] << std::endl;
    		std::cout << "MD5 Hash: " << md5sum(inFile).digest() << std::endl;
    	}
    	return 0;
    }
    

    das ganze liefert korekte ergebnisse (zumindest soweit ich es getestet habe),
    weshalb ich einfach mal davon ausgehe, dass ich es korrekt implementiert habe



  • Ehm, ja? Fragen? Probleme? Oder war das einfach für dein Mitteilungsbedürfnis?



  • @DrakoXP: Vielen Dank 👍



  • xD no problem^^

    hab wohl übersehen, dass das noch von 2008 war 😉



  • das wär sicher auch mal was interessantes fürs Magazin,
    verschiedene Implentationen von Hash-Algorithmen, die man dann auch leicht einbauen kann.

    ich beispielsweise habe vergebens im Netz nach einer Lib gesucht, in der ich einfach

    string hash = MD5("hallo welt");
    

    eingeben kann.

    bevor ich mich rangesetzt habe und die Wikipedia-Variante nachgebaut habe,
    verwendete ich auch mal OpenSSL um MD5-Hashes zu generieren, aber selbst das war
    mehr als ein simpler Funktions/Makro-Aufruf.



  • Unter Linux gibt es md5sum als Miniprogramm, Sourcen sollten auch verfuegbar sein. Desweiteren habe ich im Netz z.B. http://256.com/sources/md5/ gefunden und vieles mehr.



  • mist. so schöner code und ich habe gerade wegen http://www.mathstat.dal.ca/~selinger/md5collision/ die lust an md5 verloren.


Anmelden zum Antworten