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.