开发者

md5 a string multiple times get different result on different platform

t.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/md5.h>

static char* unsigned_to_signed_char(const unsigned char* in , int len) {
  char* res = (char*)malloc(len * 2 + 1);
  int i = 0;
  memset(res , 0 , len * 2 + 1);
  while(i < len) {
    sprintf(res + i * 2 , "%02x" , in[i]);
    i ++;
  };

  return res;
}

static unsigned char * md5(const unsigned char * in) {
  MD5_CTX ctx;
  unsigned char * result1 = (unsigned char *)malloc(MD5_DIGEST_LENGTH);
  MD5_Init(&ctx);
  printf("len: %lu \n", strlen(in));
  MD5_Update(&ctx, in, strlen(in));
  MD5_Final(result1, &ctx);
  return result1;
}


int main(int argc, char *argv[])
{
  const char * i = "abcdef";
  unsigned char * data = (unsigned char *)malloc(strlen(i) + 1);
  strncpy(data,开发者_StackOverflow i, strlen(i));  

  unsigned char * result1 = md5(data);
  free(data);
  printf("%s\n", unsigned_to_signed_char(result1, MD5_DIGEST_LENGTH));

  unsigned char * result2 = md5(result1);
  free(result1);
  printf("%s\n", unsigned_to_signed_char(result2, MD5_DIGEST_LENGTH));

  unsigned char * result3 = md5(result2);
  free(result2);
  printf("%s\n", unsigned_to_signed_char(result3, MD5_DIGEST_LENGTH));

  return 0;
}

makeflle

all:
cc t.c -Wall -L/usr/local/lib -lcrypto

and t.py

#!/usr/bin/env python

import hashlib
import binascii

src = 'abcdef'

a = hashlib.md5(src).digest()
b = hashlib.md5(a).digest()
c = hashlib.md5(b).hexdigest().upper()

print binascii.b2a_hex(a)
print binascii.b2a_hex(b)
print c

The results of python script on Debian6 x86 and MacOS 10.6 are the same:

e80b5017098950fc58aad83c8c14978e
b91282813df47352f7fe2c0c1fe9e5bd
85E4FBD1BD400329009162A8023E1E4B

the c version on MacOS is:

len: 6 
e80b5017098950fc58aad83c8c14978e
len: 48 
eac9eaa9a4e5673c5d3773d7a3108c18
len: 64 
73f83fa79e53e9415446c66802a0383f

Why it is different from Debian6 ?

Debian environment:

gcc (Debian 4.4.5-8) 4.4.5
Python 2.6.6
Linux shuge-lab 2.6.26-2-686 #1 SMP Thu Nov 25 01:53:57 UTC 2010 i686 GNU/Linux

OpenSSL was installed from testing repository.

MacOS environment:

i686-apple-darwin10-gcc-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5666) (dot 3)
Python 2.7.1
Darwin Lees-Box.local 10.7.0 Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386 i386

OpenSSL was installed from MacPort.

openssl @1.0.0d (devel, security)
    OpenSSL SSL/TLS cryptography library


I think you are allocating bytes exactly for MD5 result, without ending \0. Then you are calculating MD5 of block of memory that starts with result from previous MD5 calculating but with some random bytes after it. You should allocate one byte more for result and set it to \0.

My proposal:

...
unsigned char * result1 = (unsigned char *)malloc(MD5_DIGEST_LENGTH + 1);
result1[MD5_DIGEST_LENGTH] = 0;
...


The answers so far don't seem to me to have stated the issue clearly enough. Specifically the problem is the line:

  MD5_Update(&ctx, in, strlen(in));

The data block you pass in is not '\0' terminated, so the call to update may try to process further bytes beyond the end of the MD5_DIGEST_LENGTH buffer. In short, stop using strlen() to work out the length of an arbitrary buffer of bytes: you know how long the buffers are supposed to be so pass the length around.


You don't '\0' terminate the string you're passing to md5 (which I suppose takes a '\0' terminated string, since you don't pass it the length). The code

memset( data, 0, sizeof( strlen( i ) ) );
memcpy( data, i, strlen( i ) );

is completely broken: sizeof( strlen( i ) ) is the same as sizeof( size_t ), 4 or 8 on typical machines. But you don't want the memset anyway. Try replacing these with:

strcpy( data, i );

Or better yet:

std::string i( "abcdef" );

, then pass i.c_str() to md5 (and declare md5 to take a char const*. (I'd use an std::vector<unsigned char> in md5() as well, and have it return it. And unsigned_to_signed_char would take the std::vector<unsigned char> and return std::string.)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜