diff --git a/md5.c b/md5.c index b024e63..ba72eb9 100644 --- a/md5.c +++ b/md5.c @@ -270,3 +270,50 @@ void MD5_Final(unsigned char *result, MD5_CTX *ctx) memset(ctx, 0, sizeof(*ctx)); } + +void MD5_Hmac(unsigned char *result, const void *data, unsigned long size, const void *key, unsigned long key_size) +{ + MD5_CTX ctx; + unsigned char block[MD5_BLOCK_SZ]; + + unsigned char short_key[MD5_DIGEST_SZ]; + unsigned char temp[MD5_DIGEST_SZ]; + + const unsigned char *used_key; + int i; + + if (key_size > MD5_BLOCK_SZ) + { + MD5_Init(&ctx); + MD5_Update(&ctx, key, key_size); + MD5_Final(short_key, &ctx); + used_key = short_key; + key_size = MD5_DIGEST_SZ; + } + else + { + used_key = key; + } + + MD5_Init(&ctx); + + memset(block, 0x36, MD5_BLOCK_SZ); + for (i = 0; i < key_size; i++) + block[i] ^= used_key[i]; + MD5_Update(&ctx, block, MD5_BLOCK_SZ); + + MD5_Update(&ctx, data, size); + + MD5_Final(temp, &ctx); + + MD5_Init(&ctx); + + memset(block, 0x5c, MD5_BLOCK_SZ); + for (i = 0; i < key_size; i++) + block[i] ^= used_key[i]; + MD5_Update(&ctx, block, MD5_BLOCK_SZ); + + MD5_Update(&ctx, temp, sizeof(temp)); + + MD5_Final(result, &ctx); +} diff --git a/md5.h b/md5.h index 971c3e6..823275e 100644 --- a/md5.h +++ b/md5.h @@ -25,5 +25,6 @@ typedef struct { extern void MD5_Init(MD5_CTX *ctx); extern void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size); extern void MD5_Final(unsigned char *result, MD5_CTX *ctx); +extern void MD5_Hmac(unsigned char *result, const void *data, unsigned long size, const void *key, unsigned long key_size); #endif /* __MD5_H__ */