HiveBrain v1.2.0
Get Started
← Back to all entries
patterncModerate

Embed MD5 digest in a directory path name

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
directorypathmd5digestnameembed

Problem

My boss needs me to embed the MD5 digest in a file path, but the problem is MD5 contains escape characters.

I've already taught about a uc%duc%d... format, but it also makes lengthy file names. In Linux it's not a problem since the Linux kernel could handle them.

char * uc_encode_md5(const char * password)
{
  char digest_output[1024];
  MD5_CTX md5_ctx ;
  MD5_Init(&md5_ctx);
  MD5_Update(&md5_ctx,password,strlen(password));
  MD5_Final((unsigned char*) digest_output,&md5_ctx);
  char* ret = (char*) malloc(500);
  int len=0;
  int i ;
  for(i=0;i<16;i++)
  {
   len+= sprintf(&ret[len],"uc%d",(unsigned char)digest_output[i]); 
  }

  return ret;
}


Any better way than this? Since my just boss shared what to do, but not how to do it: what's the best practice here?

How about #ifdef's? I could suggest more formats on here and let him choose when I get back to him later tonight.

For example:

char * uc_encode_md5(const char * password)
{
#ifdef _UC_PATH_ENCODE_
  char digest_output[1024];
  MD5_CTX md5_ctx ;
  MD5_Init(&md5_ctx);
  MD5_Update(&md5_ctx,password,strlen(password));
  MD5_Final((unsigned char*) digest_output,&md5_ctx);
  char* ret = (char*) malloc(500);
  int len=0;
  int i ;
  for(i=0;i<16;i++)
  {
   len+= sprintf(&ret[len],"uc%d",(unsigned char)digest_output[i]); 
  }
#endif /* endif _UC_PATH_ENCODE_ */
  return ret;
}

Solution

MD5 is simply a 128 bit number.

Convert the number into a string that is the ASCII representation of the number. Note: Usually this is done as hex number. If you make sure it is 0 padded it will be 32 characters long (as each 8 bits is converted into two hex digits).

This is how I would do it:

static_assert(sizeof(int) == 4, "Figure it out with other sizes");

int*  data = reinterpret_cast(ret);
int   len  = 128 / (sizeof(int) * 8);

for(int i=len-1; i >= 0; --i)
{
    std::cout << std::setfill('0') << std::setw(8) << std::hex << data[i];
}

Code Snippets

static_assert(sizeof(int) == 4, "Figure it out with other sizes");

int*  data = reinterpret_cast<int*>(ret);
int   len  = 128 / (sizeof(int) * 8);

for(int i=len-1; i >= 0; --i)
{
    std::cout << std::setfill('0') << std::setw(8) << std::hex << data[i];
}

Context

StackExchange Code Review Q#41272, answer score: 10

Revisions (0)

No revisions yet.