@silky - kein wirklich hilfreicher Kommentar :) ..Die Implementierung von MD5 von Grund auf ist ein guter Weg, um sich mit kryptografischen Algorithmen und Protokollen vertraut zu machen. Da es "bekannt" ist, können Sie sofort überprüfen, ob Ihr Code richtig ist md5sumoder ähnlich
warren
1
@Noon Silk Ich denke, um hier eine eindeutige Signatur für eine Datei md5 zu erstellen, sollte dies angemessen sein.
Bobobobo
@Noon Silk, mit langen rekursiven Prüfungen wäre sha1 zu langsam!
Will03uk
Antworten:
48
Hier ist eine einfache Implementierung des md5sumBefehls, der die MD5 der in der Befehlszeile angegebenen Datei berechnet und anzeigt. Es muss mit der OpenSSL-Bibliothek ( gcc md5.c -o md5 -lssl) verknüpft sein , damit es funktioniert. Es ist reines C, aber Sie sollten es leicht genug an Ihre C ++ - Anwendung anpassen können.
#include<sys/types.h>#include<sys/stat.h>#include<sys/mman.h>#include<fcntl.h>#include<stdio.h>#include<stdlib.h>#include<string.h>#include<openssl/md5.h>unsignedchar result[MD5_DIGEST_LENGTH];
// Print the MD5 sum as hex-digits.voidprint_md5_sum(unsignedchar* md){
int i;
for(i=0; i <MD5_DIGEST_LENGTH; i++) {
printf("%02x",md[i]);
}
}
// Get the size of the file by its file descriptorunsignedlongget_size_by_fd(int fd){
structstatstatbuf;if(fstat(fd, &statbuf) < 0) exit(-1);
return statbuf.st_size;
}
intmain(int argc, char *argv[]){
int file_descript;
unsignedlong file_size;
char* file_buffer;
if(argc != 2) {
printf("Must specify the file\n");
exit(-1);
}
printf("using file:\t%s\n", argv[1]);
file_descript = open(argv[1], O_RDONLY);
if(file_descript < 0) exit(-1);
file_size = get_size_by_fd(file_descript);
printf("file size:\t%lu\n", file_size);
file_buffer = mmap(0, file_size, PROT_READ, MAP_SHARED, file_descript, 0);
MD5((unsignedchar*) file_buffer, file_size, result);
munmap(file_buffer, file_size);
print_md5_sum(result);
printf(" %s\n", argv[1]);
return0;
}
Auf 32-Bit-Plattformen kann Ihre mmap die Größe der Datei einschränken, obwohl dies eine elegante Lösung für das Problem darstellt. Unter 32-Bit-Windows konnten Sie beispielsweise keine DVD mit diesem Code auf MD5 erstellen.
Chris K
@ ChrisKaminski Sie können 4 GB Fenster der Speicherzuordnungsdatei auf 32-Bit-Plattform schieben.
Experte
12
Ausgezeichnete Antwort, es hat mir sehr geholfen. Sie rufen danach jedoch keine Munmap mehr auf. Es ist kein Speicherverlust für Sie, da das Programm unmittelbar danach endet, aber wenn ein Trottel wie ich den Code kopiert und keine Munmap einfügt, erhalten wir einen Speicherverlust in unserem Programm;) Die Lösung: munmap (file_buffer, file_size);
Bob Miller
8
Für mich gcc md5.c -o md5 -lcryptofunktionierte dies anstelle von -lsslUbuntu 14.04
RajaRaviVarma
1
Abhängig von openssl - einer riesigen und knorrigen Bibliothek - scheint mir etwas so Einfaches wie MD5 eine schlechte Idee zu sein.
Timmmm
22
Sie können den MD5-Algorithmus selbst implementieren (Beispiele finden Sie im gesamten Web), oder Sie können eine Verknüpfung mit den OpenSSL-Bibliotheken herstellen und die Digest-Funktionen von OpenSSL verwenden. Hier ist ein Beispiel, um die MD5 eines Byte-Arrays zu erhalten:
Wenn ich Qt benutze (wie Sie), würde ich es lieber nur return QCryptographicHash::hash(data, QCryptographicHash::Md5);als Hauptteil der Funktion tun ...
Akira
5
Wenn es um sicherheitsrelevante Dinge geht, schreiben Sie niemals Ihre eigene Implementierung, wenn die Dinge im Internet ausreichen. Und jede mögliche Implementierung von MD4 / 5 ist da draußen, also gibt es wirklich keinen Grund, eine eigene zu schreiben.
Mahmoud Al-Qudsi
1
@ MahmoudAl-Qudsi Ähm ja, mein Professor lässt mich keinen Code plagiieren.
b1nary.atr0phy
2
@ MahmoudAl-Qudsi Verwenden Sie niemals MD5, wenn es um sicherheitsrelevante Dinge geht . MD5 ist kein Hash mit Kryptostärke.
uliwitness
1
@uliwitness md5 war nicht meine Idee. Es ist in Ordnung, MD5 als mittelschnellen Nicht-Krypto-Hash zu behandeln, aber ich stimme zu, dass es als Krypto-Hash völlig kaputt ist (und es gibt weitaus bessere Geschwindigkeit und Hashing für Nicht-Krypto-Hashes).
Nicht so gut für Dateien mit einer Größe von GB :)
schnell_now
8
Ich musste dies gerade tun und benötigte eine plattformübergreifende Lösung, die für C ++ 11, Boost und OpenSSL geeignet war. Ich nahm die Lösung von D'Nabre als Ausgangspunkt und brachte sie auf Folgendes:
Wenn Sie in VC ++ 2010 kompilieren, müssen Sie seine main.cpp folgendermaßen ändern:
#include<iostream> //for std::cout#include<string.h> //for std::string#include"MD5.h"usingstd::cout; usingstd::endl;
intmain(int argc, char *argv[]){
std::string Temp = md5("The quick brown fox jumps over the lazy dog");
cout << Temp.c_str() << endl;
return0;
}
Sie müssen die MD5-Klasse geringfügig ändern, wenn Sie ein char * -Array anstelle einer Zeichenfolge einlesen möchten, um die Frage auf dieser Seite hier zu beantworten.
BEARBEITEN:
Anscheinend ist das Ändern der MD5-Bibliothek nicht klar. Nun, eine vollständige VC ++ 2010-Lösung ist für Sie da, um char * 's einzuschließen:
Es werden andere Hashes als bei anderen MD5-Implementierungen zurückgegeben. Beispielsweise wird eine leere Zeichenfolge an e4c23762ed2823a27e62a64b95c024e7 gehasht, wenn sie d41d8cd98f00b204e9800998ecf8427e sein soll. Es gibt dort eine verwandte Frage: stackoverflow.com/q/33989390/2436687
user31389
3
Ich habe Botan verwendet , um diese und andere Operationen durchzuführen. AraK hat auf Crypto ++ hingewiesen. Ich denke, beide Bibliotheken sind vollkommen gültig. Jetzt liegt es an dir :-).
Ich brauche etwas sehr Ähnliches, weil ich keine Multi-Gigabyte-Dateien einlesen kann, nur um einen Hash zu berechnen. Theoretisch könnte ich sie speichern, aber ich muss 32-Bit-Plattformen unterstützen - das ist immer noch problematisch für große Dateien.
md5sum
oder ähnlichAntworten:
Hier ist eine einfache Implementierung des
md5sum
Befehls, der die MD5 der in der Befehlszeile angegebenen Datei berechnet und anzeigt. Es muss mit der OpenSSL-Bibliothek (gcc md5.c -o md5 -lssl
) verknüpft sein , damit es funktioniert. Es ist reines C, aber Sie sollten es leicht genug an Ihre C ++ - Anwendung anpassen können.#include <sys/types.h> #include <sys/stat.h> #include <sys/mman.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <openssl/md5.h> unsigned char result[MD5_DIGEST_LENGTH]; // Print the MD5 sum as hex-digits. void print_md5_sum(unsigned char* md) { int i; for(i=0; i <MD5_DIGEST_LENGTH; i++) { printf("%02x",md[i]); } } // Get the size of the file by its file descriptor unsigned long get_size_by_fd(int fd) { struct stat statbuf; if(fstat(fd, &statbuf) < 0) exit(-1); return statbuf.st_size; } int main(int argc, char *argv[]) { int file_descript; unsigned long file_size; char* file_buffer; if(argc != 2) { printf("Must specify the file\n"); exit(-1); } printf("using file:\t%s\n", argv[1]); file_descript = open(argv[1], O_RDONLY); if(file_descript < 0) exit(-1); file_size = get_size_by_fd(file_descript); printf("file size:\t%lu\n", file_size); file_buffer = mmap(0, file_size, PROT_READ, MAP_SHARED, file_descript, 0); MD5((unsigned char*) file_buffer, file_size, result); munmap(file_buffer, file_size); print_md5_sum(result); printf(" %s\n", argv[1]); return 0; }
quelle
gcc md5.c -o md5 -lcrypto
funktionierte dies anstelle von-lssl
Ubuntu 14.04Sie können den MD5-Algorithmus selbst implementieren (Beispiele finden Sie im gesamten Web), oder Sie können eine Verknüpfung mit den OpenSSL-Bibliotheken herstellen und die Digest-Funktionen von OpenSSL verwenden. Hier ist ein Beispiel, um die MD5 eines Byte-Arrays zu erhalten:
#include <openssl/md5.h> QByteArray AESWrapper::md5 ( const QByteArray& data) { unsigned char * tmp_hash; tmp_hash = MD5((const unsigned char*)data.constData(), data.length(), NULL); return QByteArray((const char*)tmp_hash, MD5_DIGEST_LENGTH); }
quelle
return QCryptographicHash::hash(data, QCryptographicHash::Md5);
als Hauptteil der Funktion tun ...QFile file("bigimage.jpg"); if (file.open(QIODevice::ReadOnly)) { QByteArray fileData = file.readAll(); QByteArray hashData = QCryptographicHash::hash(fileData,QCryptographicHash::Md5); // or QCryptographicHash::Sha1 qDebug() << hashData.toHex(); // 0e0c2180dfd784dd84423b00af86e2fc }
quelle
Ich musste dies gerade tun und benötigte eine plattformübergreifende Lösung, die für C ++ 11, Boost und OpenSSL geeignet war. Ich nahm die Lösung von D'Nabre als Ausgangspunkt und brachte sie auf Folgendes:
#include <openssl/md5.h> #include <iomanip> #include <sstream> #include <boost/iostreams/device/mapped_file.hpp> const std::string md5_from_file(const std::string& path) { unsigned char result[MD5_DIGEST_LENGTH]; boost::iostreams::mapped_file_source src(path); MD5((unsigned char*)src.data(), src.size(), result); std::ostringstream sout; sout<<std::hex<<std::setfill('0'); for(auto c: result) sout<<std::setw(2)<<(int)c; return sout.str(); }
Eine ausführbare Testdatei zeigt:
#include <iostream> int main(int argc, char *argv[]) { if(argc != 2) { std::cerr<<"Must specify the file\n"; exit(-1); } std::cout<<md5_from_file(argv[1])<<" "<<argv[1]<<std::endl; return 0; }
Einige Verknüpfungshinweise: Linux:
-lcrypto -lboost_iostreams
Windows:-DBOOST_ALL_DYN_LINK libeay32.lib ssleay32.lib
quelle
Für alle, die von " /programming/4393017/md5-implementation-in-c " umgeleitet wurden, weil es fälschlicherweise als Duplikat gekennzeichnet wurde.
Das hier gezeigte Beispiel funktioniert:
http://www.zedwood.com/article/cpp-md5-function
Wenn Sie in VC ++ 2010 kompilieren, müssen Sie seine main.cpp folgendermaßen ändern:
#include <iostream> //for std::cout #include <string.h> //for std::string #include "MD5.h" using std::cout; using std::endl; int main(int argc, char *argv[]) { std::string Temp = md5("The quick brown fox jumps over the lazy dog"); cout << Temp.c_str() << endl; return 0; }
Sie müssen die MD5-Klasse geringfügig ändern, wenn Sie ein char * -Array anstelle einer Zeichenfolge einlesen möchten, um die Frage auf dieser Seite hier zu beantworten.
BEARBEITEN:
Anscheinend ist das Ändern der MD5-Bibliothek nicht klar. Nun, eine vollständige VC ++ 2010-Lösung ist für Sie da, um char * 's einzuschließen:
https://github.com/alm4096/MD5-Hash-Example-VS
Eine kleine Erklärung finden Sie hier:
#include <iostream> //for std::cout #include <string.h> //for std::string #include <fstream> #include "MD5.h" using std::cout; using std::endl; int main(int argc, char *argv[]) { //Start opening your file ifstream inBigArrayfile; inBigArrayfile.open ("Data.dat", std::ios::binary | std::ios::in); //Find length of file inBigArrayfile.seekg (0, std::ios::end); long Length = inBigArrayfile.tellg(); inBigArrayfile.seekg (0, std::ios::beg); //read in the data from your file char * InFileData = new char[Length]; inBigArrayfile.read(InFileData,Length); //Calculate MD5 hash std::string Temp = md5(InFileData,Length); cout << Temp.c_str() << endl; //Clean up delete [] InFileData; return 0; }
Ich habe der MD5-Bibliothek einfach Folgendes hinzugefügt:
MD5.cpp:
MD5::MD5(char * Input, long length) { init(); update(Input, length); finalize(); }
MD5.h:
std::string md5(char * Input, long length);
quelle
Ich benutze diese Datei http://people.csail.mit.edu/rivest/Md5.c
quelle
Ich habe Botan verwendet , um diese und andere Operationen durchzuführen. AraK hat auf Crypto ++ hingewiesen. Ich denke, beide Bibliotheken sind vollkommen gültig. Jetzt liegt es an dir :-).
quelle
Mit Crypto ++ können Sie Folgendes tun:
#include <sha.h> #include <iostream> SHA256 sha; while ( !f.eof() ) { char buff[4096]; int numchars = f.read(...); sha.Update(buff, numchars); } char hash[size]; sha.Final(hash); cout << hash <<endl;
Ich brauche etwas sehr Ähnliches, weil ich keine Multi-Gigabyte-Dateien einlesen kann, nur um einen Hash zu berechnen. Theoretisch könnte ich sie speichern, aber ich muss 32-Bit-Plattformen unterstützen - das ist immer noch problematisch für große Dateien.
quelle
Die Implementierung von John Walker wird mit Quellen geliefert .
quelle
Unter http://256stuff.com/sources/md5/ gibt es eine hübsche Bibliothek mit Anwendungsbeispielen. Dies ist die einfachste Bibliothek für MD5.
quelle
Eine Überarbeitung der Implementierung von @ D'Nabre für C ++. Vergessen Sie nicht, am Ende mit -lcrypto zu kompilieren :
gcc md5.c -o md5 -lcrypto
.#include <iostream> #include <iomanip> #include <fstream> #include <string> #include <openssl/md5.h> using namespace std; unsigned char result[MD5_DIGEST_LENGTH]; // function to print MD5 correctly void printMD5(unsigned char* md, long size = MD5_DIGEST_LENGTH) { for (int i=0; i<size; i++) { cout<< hex << setw(2) << setfill('0') << (int) md[i]; } } int main(int argc, char *argv[]) { if(argc != 2) { cout << "Specify the file..." << endl; return 0; } ifstream::pos_type fileSize; char * memBlock; ifstream file (argv[1], ios::ate); //check if opened if (file.is_open() ) { cout<< "Using file\t"<< argv[1]<<endl; } else { cout<< "Unnable to open\t"<< argv[1]<<endl; return 0; } //get file size & copy file to memory //~ file.seekg(-1,ios::end); // exludes EOF fileSize = file.tellg(); cout << "File size \t"<< fileSize << endl; memBlock = new char[fileSize]; file.seekg(0,ios::beg); file.read(memBlock, fileSize); file.close(); //get md5 sum MD5((unsigned char*) memBlock, fileSize, result); //~ cout << "MD5_DIGEST_LENGTH = "<< MD5_DIGEST_LENGTH << endl; printMD5(result); cout<<endl; return 0; }
quelle
md5.h
haben auchMD5_*
Funktionen sehr nützlich für große Dateien#include <openssl/md5.h> #include <fstream> ....... std::ifstream file(filename, std::ifstream::binary); MD5_CTX md5Context; MD5_Init(&md5Context); char buf[1024 * 16]; while (file.good()) { file.read(buf, sizeof(buf)); MD5_Update(&md5Context, buf, file.gcount()); } unsigned char result[MD5_DIGEST_LENGTH]; MD5_Final(result, &md5Context);
Sehr einfach, nicht wahr? Konvertierung in String auch sehr einfach:
#include <sstream> #include <iomanip> ....... std::stringstream md5string; md5string << std::hex << std::uppercase << std::setfill('0'); for (const auto &byte: result) md5string << std::setw(2) << (int)byte; return md5string.str();
quelle