Hash functions

Most commonly used List of hashes and their lengths:

hash algorithm length bytes
MD5 16
SHA1 20
SHA256 32
SHA384 32
SHA512 64

OpenSSL EVP interface can be used to perform Digest calculations. Most commonly used APIs are below.

int EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type);

int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl);

int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *d, size_t cnt);

int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s);

The EVP_DigestInit and EVP_DigestInit_ex are similar except that the EVP_DigestInit_ex accepts an implementation specific pointer. The EVPDigestInit_ex sets up the given digest context ctx from the given type.

For this first the ctx must be initialised. This can be done using the EVP_MD_CTX_init function. The prototype is as follows.

void EVP_MD_CTX_init(EVP_MD_CTX *ctx);

The initialised context can then be passed to the Digest API for hash calculation.

After the ctx is been used, it needs to be released with EVP_MD_CTX_destroy.

A simple hash calculation for a given input buffer is as follows.

#include <iostream>
#include <stdint.h>
#include <openssl/conf.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <openssl/md5.h>
#include <openssl/rand.h>

int main()
{
    EVP_MD_CTX *ctx;
    const EVP_MD *md;

    // create md context
    ctx = EVP_MD_CTX_create();
    if (!ctx) {
        return -1;
    }

    // initialise the MD to use sha256
    md = EVP_sha256();
    if (!md) {
        return -1;
    }

    int ret;

    // initialise the digest
    ret = EVP_DigestInit_ex(ctx, md, NULL);
    if (ret != 1) {
        return -1;
    }

    std::string input = "hash function";

    // update digest with the given input buffer
    ret = EVP_DigestUpdate(ctx, input.c_str(), input.length());
    if (ret != 1) {
        return -1;
    }

    uint8_t sha256_hash[32];
    int sha256_hashlen = 0;

    // calculate the final hash
    ret = EVP_DigestFinal_ex(ctx, sha256_hash, (unsigned int *)&sha256_hashlen);
    if (ret != 1) {
        return -1;
    }

    // dump the final hash
    int i;

    printf("sha256: ");
    for (i = 0; i < sha256_hashlen; i ++) {
        printf("%02x", sha256_hash[i]);
    }
    printf("\n");

    // destroy md context
    EVP_MD_CTX_destroy(ctx);

    return 0;
}

The MD algorithm here used is the SHA256. The function EVP_sha256 returns a constant pointer to EVP_MD.

There are many hashing algorithms in the library, for ex,

const EVP_MD *EVP_md_null(void);
const EVP_MD *EVP_md2(void);
const EVP_MD *EVP_md5(void);
const EVP_MD *EVP_sha(void);
const EVP_MD *EVP_sha1(void);
const EVP_MD *EVP_sha224(void);
const EVP_MD *EVP_sha256(void);
const EVP_MD *EVP_sha384(void);
const EVP_MD *EVP_sha512(void);
const EVP_MD *EVP_dss(void);
const EVP_MD *EVP_dss1(void);
const EVP_MD *EVP_mdc2(void);
const EVP_MD *EVP_ripemd160(void);

usually EVP_md_null initialise a null algorithm. MD2, MD5 are broken and are not preferred. Prefer always sha256 and above. Hashing algorithms are used as well in creating the message signatures for example in ECC and RSA signatures. More on this below.

To hash a file, the function EVP_DigestUpdate needs to be repeatedly called over the contents of file.

Refer for more APIs in here.

results matching ""

    No results matching ""