Josh1billion
Josh1billion

Reputation: 14927

C/C++ function for generating a hash for passwords (using MD5 or another algorithm)?

I'm looking for a function for C/C++ that behaves identically to PHP's md5() function -- pass in a string, return a one-way hash of that string. I'm also open to other algorithms than md5() if they are as secure (or more secure), reasonably fast, and ideally one-way.

The reason I'm searching for said function is for the same purpose I would use PHP's md5() function: to store a one-way hash of a user's password in a database rather than the actual text of the user's password (in case the database's data is ever compromised, the user's passwords would still be relatively secret).

I've spent around two hours searching now. All the code I've found either was for getting an MD5 of file data (instead of just a string), wouldn't compile, was for another programming language, or required an entire library (such as Crypto++, OpenSSL, hashlib++) to be added to my project, some of which are very large (is that really necessary when all I want is just one one-way string hashing function?).

Seeing as how this is a common need, I'm assuming someone has already written and made available exactly what I'm looking for.. can someone point me to it?

Thanks in advance.

Upvotes: 2

Views: 30826

Answers (7)

Joshua
Joshua

Reputation: 43327

SHA-1 is easy. Pseudocode here: http://en.wikipedia.org/wiki/SHA-1

HOWEVER, you need to salt your passwords. This means you save a few bytes of random data in front of the password and hashed password.

General form (salt is fixed length): salt + sha1(salt + password) = hash

Update from decade later: DO NOT USE. SHA-1 should be aged out now. The collision attack doesn't matter. SHA-1 is currently too fast and a dictionary attack is within range, salt or no salt.

Upvotes: 2

B. Nadolson
B. Nadolson

Reputation: 3068

Wikipedia's MD5 simple implementation has easy code and is very fast.

I would recommend it over the above solutions (for MD5 if it must be MD5) because it does not require an external library and the code does not contain #ifdefs

/*
 * Simple MD5 implementation
 *
 * Compile with: gcc -o md5 -O3 -lm md5.c
 *
 * NOTE: this code only works on little-endian machines.
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>

// Constants are the integer part of the sines of integers (in radians) * 2^32.
const uint32_t k[64] = {
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee ,
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501 ,
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be ,
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821 ,
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa ,
0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8 ,
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed ,
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a ,
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c ,
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70 ,
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05 ,
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665 ,
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039 ,
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1 ,
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1 ,
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 };

// leftrotate function definition
#define LEFTROTATE(x, c) (((x) << (c)) | ((x) >> (32 - (c))))

// These vars will contain the hash
uint32_t h0, h1, h2, h3;

void md5(uint8_t *initial_msg, size_t initial_len) {

    // Message (to prepare)
    uint8_t *msg = NULL;
    int new_len;
    uint32_t bits_len;
    int offset;
    uint32_t *w;
    uint32_t a, b, c, d, i, f, g, temp;

    // Note: All variables are unsigned 32 bit and wrap modulo 2^32 when calculating

    // r specifies the per-round shift amounts
    const uint32_t r[] = {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};

    // Initialize variables - simple count in nibbles:
    h0 = 0x67452301;
    h1 = 0xefcdab89;
    h2 = 0x98badcfe;
    h3 = 0x10325476;

    // Pre-processing: adding a single 1 bit
    //append "1" bit to message    
    /* Notice: the input bytes are considered as bits strings,
       where the first bit is the most significant bit of the byte.[37] */

    // Pre-processing: padding with zeros
    //append "0" bit until message length in bit ≡ 448 (mod 512)
    //append length mod (2 pow 64) to message

    for(new_len = initial_len*8 + 1; new_len%512!=448; new_len++);
    new_len /= 8;

    msg = (uint8_t*)calloc(new_len + 64, 1); // also appends "0" bits 
                                   // (we alloc also 64 extra bytes...)
    memcpy(msg, initial_msg, initial_len);
    msg[initial_len] = 128; // write the "1" bit

    bits_len = 8*initial_len; // note, we append the len
    memcpy(msg + new_len, &bits_len, 4);           // in bits at the end of the buffer

    // Process the message in successive 512-bit chunks:
    //for each 512-bit chunk of message:
    for(offset=0; offset<new_len; offset += (512/8)) {

        // break chunk into sixteen 32-bit words w[j], 0 ≤ j ≤ 15
        w = (uint32_t *) (msg + offset);

#ifdef DEBUG
        printf("offset: %d %x\n", offset, offset);

        int j;
        for(j =0; j < 64; j++) printf("%x ", ((uint8_t *) w)[j]);
        puts("");
#endif

        // Initialize hash value for this chunk:
        a = h0;
        b = h1;
        c = h2;
        d = h3;

        // Main loop:
        for(i = 0; i<64; i++) {

             if (i < 16) {
                f = (b & c) | ((~b) & d);
                g = i;
            } else if (i < 32) {
                f = (d & b) | ((~d) & c);
                g = (5*i + 1) % 16;
            } else if (i < 48) {
                f = b ^ c ^ d;
                g = (3*i + 5) % 16;          
            } else {
                f = c ^ (b | (~d));
                g = (7*i) % 16;
            }

             temp = d;
            d = c;
            c = b;
            b = b + LEFTROTATE((a + f + k[i] + w[g]), r[i]);
            a = temp;

        }

        // Add this chunk's hash to result so far:
        h0 += a;
        h1 += b;
        h2 += c;
        h3 += d;

    }

    // cleanup
    free(msg);

}

int main(int argc, char **argv) {

    if (argc < 2) {
        printf("usage: %s 'string'\n", argv[0]);
        return 1;
    }

    char *msg = argv[1];
    size_t len = strlen(msg);

    // benchmark
    int i;
    for (i = 0; i < 1000000; i++) {
        md5((uint8_t*)msg, len);
    }

    //var char digest[16] := h0 append h1 append h2 append h3 //(Output is in little-endian)
    uint8_t *p;

    // display result

    p=(uint8_t *)&h0;
    printf("%2.2x%2.2x%2.2x%2.2x", p[0], p[1], p[2], p[3], h0);

    p=(uint8_t *)&h1;
    printf("%2.2x%2.2x%2.2x%2.2x", p[0], p[1], p[2], p[3], h1);

    p=(uint8_t *)&h2;
    printf("%2.2x%2.2x%2.2x%2.2x", p[0], p[1], p[2], p[3], h2);

    p=(uint8_t *)&h3;
    printf("%2.2x%2.2x%2.2x%2.2x", p[0], p[1], p[2], p[3], h3);
    puts("");

    return 0;
}

Upvotes: 6

user849425
user849425

Reputation:

The Boost library has a fairly good implementation of the SHA-1 hash function. You can find the source for it here.

Upvotes: 0

Code Monkey
Code Monkey

Reputation: 319

here is a site that has the MD5 algorithm in many languages: http://userpages.umbc.edu/~mabzug1/cs/md5/md5.html

also if you use Visual C++, you can use .NET which has encryption support here is some documentation:

http://msdn.microsoft.com/en-us/library/system.security.cryptography.md5.aspx#Y0

hope that helps!

Upvotes: 1

Adam Rosenfield
Adam Rosenfield

Reputation: 400642

Seriously, use a library (OpenSSL is a good choice). They're well-tested, and you can just drop them into your project without having to worry if you get the code right or not. Don't worry about the size of the library, any functions you don't use will not be included in your final executable.

I'd also recommend avoiding MD5, as it has known weaknesses, in favor of something stronger such as SHA-256 or Blowfish.

But whichever algorithm and implementation you go with, do not forget to salt your inputs!

Upvotes: 8

Greg Hewgill
Greg Hewgill

Reputation: 994559

There is a reference implementation for MD5 in C at the bottom of RFC 1321, which doesn't require any extra libraries.

Upvotes: 2

jman
jman

Reputation: 11626

See crypt(). It can do MD5 when passed a specific salt.

Upvotes: 0

Related Questions