web-dev-qa-db-fra.com

Comment obtenir le hachage MD5 d'un fichier en C ++?

J'ai le chemin du fichier. Comment puis-je obtenir le hachage MD5?

69
user145586

Voici une implémentation simple du md5sum commande qui calcule et affiche le MD5 du fichier spécifié sur la ligne de commande. Il doit être lié à la bibliothèque OpenSSL (gcc md5.c -o md5 -lssl) travailler. C'est du pur C, mais vous devriez pouvoir l'adapter à votre application C++ assez facilement.

#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;
}
43
D'Nabre

Vous pouvez implémenter l'algorithme MD5 vous-même (les exemples se trouvent sur le Web), ou vous pouvez créer un lien avec les bibliothèques OpenSSL et utiliser les fonctions de synthèse OpenSSL. voici un exemple pour obtenir le MD5 d'un tableau d'octets:

#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);
}
21
OneOfOne
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

}
9
iyiy

Je devais le faire tout à l'heure et j'avais besoin d'une solution multiplate-forme adaptée à c ++ 11, boost et openssl. J'ai pris la solution de de D'Nabre comme point de départ et je l'ai résumée comme suit:

#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();
}

Un exécutable de test rapide montre:

#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;
}

Quelques notes de liens: Linux: -lcrypto -lboost_iostreams Les fenêtres: -DBOOST_ALL_DYN_LINK libeay32.lib ssleay32.lib

8
Benedict

Pour toute personne redirigée à partir de " https://stackoverflow.com/questions/4393017/md5-implementation-in-c " car il a été incorrectement étiqueté un doublon.

L'exemple situé ici fonctionne:

http://www.zedwood.com/article/cpp-md5-function

Si vous compilez dans VC++ 2010, vous devrez changer son fichier main.cpp en ceci:

#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;
}

Vous devrez modifier légèrement la classe MD5 si vous souhaitez lire un tableau char * au lieu d'une chaîne pour répondre à la question de cette page ici.

MODIFIER:

Apparemment, la modification de la bibliothèque MD5 n’est pas claire. Une solution Full VC++ 2010 est là pour vous permettre d’inclure les caractères car *:

https://github.com/alm4096/MD5-Hash-Example-VS

Une petite explication est ici:

#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;
}

J'ai simplement ajouté ce qui suit dans la bibliothèque MD5:

MD5.cpp:

MD5::MD5(char * Input, long length)
{
  init();
  update(Input, length);
  finalize();
}

MD5.h:

std::string md5(char * Input, long length);
7
ALM865
4
Ulterior

J'ai utilisé Botan pour effectuer cette opération et d'autres auparavant. AraK a souligné Crypto ++. Je suppose que les deux bibliothèques sont parfaitement valables. Maintenant, à vous de jouer :-).

3
javier-sanz

Il existe une jolie bibliothèque sur http://256stuff.com/sources/md5/ , avec un exemple d'utilisation. C'est la bibliothèque la plus simple pour MD5.

2
user176443
2

Un remaniement de l'imementation par @ D'Nabre pour C++. N'oubliez pas de compiler avec -lcrypto à la fin: 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;
}
1
mr. Y

En utilisant Crypto ++, vous pouvez effectuer les opérations suivantes:

#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; 

J'ai besoin de quelque chose de très similaire, car je ne peux pas lire dans des fichiers de plusieurs gigaoctets pour calculer un hachage. En théorie, je pourrais les mapper en mémoire, mais je dois prendre en charge les plates-formes 32 bits - cela reste problématique pour les gros fichiers.

1
Chris K

md5.h ont aussi MD5_* fonctions très utiles pour les gros fichiers

#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);

Très simple, n'est-ce pas? La conversion en chaîne est également très simple:

#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();
1
mr NAE