Boost logo

Boost Users :

From: Bill Lear (rael_at_[hidden])
Date: 2007-11-07 21:10:56


On Wednesday, November 7, 2007 at 23:45:13 (+0000) Daniel James writes:
>Mark Wyszomierski wrote:
>> Hi,
>>
>> I'm trying to hash a string, something like:
>>
>> 1) Take string (password) from user
>> 2) Hash it
>> 3) Store to disk
>>
>> I see boost has some hashing features, but am not quite sure how they
>> work. Do they do this type of thing? I'm looking for some really
>> simple hashing, this is just for a simple application.
>
>No, they're not suitable. Boost.Hash is designed to be used with in
>memory hash tables.
>
>You probably need a cryptographic hash, such as MD5 or one of the SHA
>hash functions. I think the Adobe Source Libraries include these. And
>there has also been talk of implementations for boost in the past (check
>the vault and/or archives) but I don't think anything has been put
>forward for review.

This might be of use... may need some rejiggering.

// .hh file
#include <vector>
#include <string>
#include <iosfwd>
#include <openssl/evp.h>

// Generates a SHA1 checksum for the given stream
std::vector<unsigned char> sha1sum(std::istream&);

// Generates a SHA1 checksum for the given file
std::vector<unsigned char> sha1sum(const std::string&);

// converts the sha1sum vector to a hexadecimal string
std::string sha1_to_string(const std::vector<unsigned char>&);

//---------------------------------------------------------------------------//
// Provides, inter alia, semantics to support intermediate calculation of
// sha1 checksums. This is useful, for example, in graph traversal, during
// which you may want to know the sha1 sum of the current path. The
// underlying implementation does not allow "un-digesting" of content,
// so testing to see if a current node in a path creates a sha1 that
// has been seen before *without modifying the current path's sha1*
// requires a copy of the Sum object to a temporary object,
// the addition of the node, and test to see if the new sha1 has been
// seen.
//---------------------------------------------------------------------------//
class Sum {
public:
    Sum();
    ~Sum();

    Sum(const Sum&);
    Sum& operator = (const Sum&);

    // Add new content
    void digest(const char*, size_t);
    void digest(const std::string&);

    // Get sha1 value; digest() may be called again
    std::string sha1();

private:
    const EVP_MD* md;
    EVP_MD_CTX mdctx;
};

// .cc file
#include <fstream>
#include <stdio.h>

using namespace std;

vector<unsigned char> sha1sum(istream& is) {
    const EVP_MD* md = EVP_sha1();

    Insist(md, "Unable to get sha1 message digest structure");

    OpenSSL_add_all_digests();

    EVP_MD_CTX mdctx;
    EVP_MD_CTX_init(&mdctx);
    EVP_DigestInit_ex(&mdctx, md, NULL);

    const size_t buffer_length = 1024 * 1024;
    static char buffer[buffer_length];
    while (true) {
        is.read(buffer, buffer_length);
        if (!is.gcount()) {
            break;
        }
        EVP_DigestUpdate(&mdctx, buffer,
                         static_cast<unsigned int>(is.gcount()));
    }

    unsigned char md_value[EVP_MAX_MD_SIZE];
    unsigned int md_len = 0;
    EVP_DigestFinal_ex(&mdctx, md_value, &md_len);

    EVP_MD_CTX_cleanup(&mdctx);

    return vector<unsigned char>(md_value, md_value + md_len);
}

vector<unsigned char> sha1sum(const string& filename) {
    ifstream is(filename.c_str());

    Insist(is.good(), "Unable to open " + filename + " for reading." );

    return sha1sum(is);
}

string sha1_to_string(const vector<unsigned char>& v) {
    string sha1;

    for (vector<unsigned char>::const_iterator i = v.begin(); i != v.end(); ++i)
 {
        char b[8];
        sprintf(b, "%02x", *i);
        sha1 += b;
    }

    return sha1;
}

Sum::Sum() : md(EVP_sha1()) {
    Insist(md, "Unable to get sha1 message digest structure");

    OpenSSL_add_all_digests();

    EVP_MD_CTX_init(&mdctx);
    EVP_DigestInit_ex(&mdctx, md, NULL);
}

Sum::~Sum() {
    EVP_MD_CTX_cleanup(&mdctx);
}

Sum::Sum(const Sum& other) : md(EVP_sha1()) {
    Insist(md, "Unable to get sha1 message digest structure");

    OpenSSL_add_all_digests();

    EVP_MD_CTX_init(&mdctx);
    EVP_DigestInit_ex(&mdctx, md, NULL);

    EVP_MD_CTX_copy_ex(&mdctx, &other.mdctx);
}

Sum& Sum::operator = (const Sum& other) {
    if (this != &other) {
        EVP_MD_CTX_copy_ex(&mdctx, &other.mdctx);
    }
    return *this;
}

void Sum::digest(const char* buffer, size_t length) {
    EVP_DigestUpdate(&mdctx, buffer, static_cast<unsigned int>(length));
}

void Sum::digest(const string& buffer) {
    EVP_DigestUpdate(&mdctx, buffer.c_str(),
                     static_cast<unsigned int>(buffer.size()));
}

string Sum::sha1() {
    EVP_MD_CTX mdctx_tmp;
    EVP_MD_CTX_copy(&mdctx_tmp, &mdctx);

    unsigned char md_value[EVP_MAX_MD_SIZE];
    unsigned int md_len = 0;
    EVP_DigestFinal_ex(&mdctx_tmp, md_value, &md_len);

    EVP_MD_CTX_cleanup(&mdctx_tmp);

    vector<unsigned char> v(md_value, md_value + md_len);

    return sha1_to_string(v);
}

Bill


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net