Saturday, June 20, 2015

Gotcha's for computing SHA1 with openssl (C, clang)

  • Don't forget to link to lib crypto when compiling with clang: 
clang -lcrypto main.c
otherwise you will get unrecognised symbol errors for the evp functions (EVP_MD_CTX_init etc.)
  • Use <openssl/evp.h>, not the deprecated <openssl/sha.h>
  • Don't forget the call to OpenSSL_add_all_algorithms()before calling the hash functions, otherwise EVP_get_digestbyname will return null for 'SHA1'
  • SHA1 is a 160 bit hash. We want to look at it as a 40 digits long hex number, so remember to allocate a buffer of 40 unsigned chars to be passed to the hash function. Use a const like const size_t SHA_DIGEST_LENGTH = 40;
Here's a bit of code to get random SHA1 strings:
#include <openssl/evp.h>
#include <string.h>

const size_t SHA_DIGEST_LENGTH = 40;

/*
 * helper function to generate a random string
 */
static char *rand_string(char *str, size_t size) {
    const char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJK...";
    if (size) {
        --size;
        for (size_t n = 0; n < size; n++) {
            int key = rand() % (int) (sizeof charset - 1);
            str[n] = charset[key];
        }
        str[size] = '\0';
    }
    return str;
}

unsigned int hash(const char *mode, const char* dataToHash, size_t dataSize, unsigned char* outHashed) {
    unsigned int md_len = -1;
    const EVP_MD *md = EVP_get_digestbyname(mode);
    if(NULL != md) {
        EVP_MD_CTX mdctx;
        EVP_MD_CTX_init(&mdctx);
        EVP_DigestInit_ex(&mdctx, md, NULL);
        EVP_DigestUpdate(&mdctx, dataToHash, dataSize);
        EVP_DigestFinal_ex(&mdctx, outHashed, &md_len);
        EVP_MD_CTX_cleanup(&mdctx);
    }
    return md_len;
}

/*
 * helper function to generate a random sha1 hash
 */
 unsigned char* getRandomSHA1() {
    const size_t BUFFER_SIZE = 40;
    char *buffer = (char*)malloc(sizeof(char) * BUFFER_SIZE);   
    rand_string(buffer, BUFFER_SIZE);
    unsigned char *outHash = (unsigned char*)malloc(sizeof(unsigned char) * SHA_DIGEST_LENGTH); 
    hash("SHA1", buffer, strlen(buffer), outHash);
    return outHash;
 }

No comments:

Post a Comment