#include "sechash.h"
#include "xp_md5.h"
#include "xp_mem.h"
#include "xpassert.h"
/*
* XP_Md5Binary(data, digest)
* calculates the MD5 signature for 'data' which is NULL-terminated,
* and places the 16-byte binary signature into 'digest' which must
* be allocated by the caller.
*
*/
PUBLIC void XP_Md5Binary(char *data, int len, unsigned char digest[16])
{
MD5_HashBuf(digest, (unsigned char *)data, len);
}
static char xp_pr[] = "0123456789abcdefghijklmnopqrstuv";
/*
* XP_Md5PCPrintable(data, len)
* Makes a call to XP_Md5Binary, which turns a buffer of length 'len'
* into a 16 byte digest. This routine then turns the 16 binary bytes
* into 24 readable bytes. It is the responsibility of the caller
* to free this string.
*
* This maps only five bits to each char to make it work on the
* braindead, case-insensitive-filesystem PC, aaaarrgh.
*
* So for each 5 bytes it takes, it gives 8 printable bytes,
* with bits taken from original data as follows:
*
* [byte][bit]..[byte][bit] byte=0..4, bit=1..8
*
* [0][1]..[0][5]
* [0][6]..[1][2]
* [1][3]..[1][7]
* [1][8]..[2][4]
* [2][5]..[3][1]
* [3][2]..[3][6]
* [3][7]..[4][3]
* [4][4]..[4][8]
*
*/
PUBLIC char *XP_Md5PCPrintable(char *data, int len)
{
unsigned char digest[16];
char* buf = (char*) XP_ALLOC(25); /* 16 bytes -> 24 printable bytes */
register int i, j;
if ( buf == NULL ) return NULL;
XP_Md5Binary(data, len, digest);
/* Aaargh, somebody come up with a more mathematical formula to do this
without hardcoded numbers.
*/
for (i=j=0; i<15; i+=5, j+=8)
{
buf[j ] = xp_pr[ (digest[i ] >> 3)];
buf[j+1] = xp_pr[((digest[i ] & 7) << 2) | (digest[i+1] >> 6)];
buf[j+2] = xp_pr[((digest[i+1] & 63) >> 1) ];
buf[j+3] = xp_pr[((digest[i+1] & 1) << 4) | (digest[i+2] >> 4)];
buf[j+4] = xp_pr[((digest[i+2] & 15) << 1) | (digest[i+3] >> 7)];
buf[j+5] = xp_pr[((digest[i+3] & 127) >> 2) ];
buf[j+6] = xp_pr[((digest[i+3] & 3) << 3) | (digest[i+4] >> 5)];
buf[j+7] = xp_pr[((digest[i+4] & 31) ) ];
}
buf[24] = '\0';
return buf;
}