MD5 строка несколько раз получить разные результаты на разных платформах - PullRequest
0 голосов
/ 06 июня 2011

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, 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

и т.пи

#!/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

Результаты сценария python для Debian6 x86 и MacOS 10.6 одинаковы:

e80b5017098950fc58aad83c8c14978e
b91282813df47352f7fe2c0c1fe9e5bd
85E4FBD1BD400329009162A8023E1E4B

версия c на MacOS:

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

Чем он отличается от Debian6?

Среда Debian:

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 был установлен из репозитория тестирования.

Среда MacOS:

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 был установлен из MacPort.

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

Ответы [ 3 ]

1 голос
/ 06 июня 2011

Ответы до сих пор, по-моему, недостаточно четко сформулировали проблему.В частности, проблема заключается в строке:

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

Передаваемый вами блок данных не '\0' завершен, поэтому вызов для обновления может попытаться обработать дополнительные байты за пределами конца буфера MD5_DIGEST_LENGTH.Короче говоря, прекратите использовать strlen() для определения длины произвольного буфера байтов: вы знаете, как долго должны быть буферы, так что передавайте длину вокруг.

1 голос
/ 06 июня 2011

Я думаю, что вы выделяете байты именно для результата MD5, не заканчивая \0. Затем вы вычисляете MD5 блока памяти, который начинается с результата предыдущего вычисления MD5, но с некоторыми случайными байтами после него. Вы должны выделить еще один байт для результата и установить его на \0.

Мое предложение:

...
unsigned char * result1 = (unsigned char *)malloc(MD5_DIGEST_LENGTH + 1);
result1[MD5_DIGEST_LENGTH] = 0;
...
0 голосов
/ 06 июня 2011

Вы не '\0' завершаете строку, которую вы передаете md5 (что, как я полагаю, принимает строку с '\0', поскольку вы не передаете ее по длине).Код

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

полностью не работает: sizeof( strlen( i ) ) совпадает с sizeof( size_t ), 4 или 8 на обычных машинах.Но ты все равно не хочешь memset.Попробуйте заменить их на:

strcpy( data, i );

Или еще лучше:

std::string i( "abcdef" );

, затем передайте i.c_str() в md5 (и объявите md5 для получения char const*.(Я бы также использовал std::vector<unsigned char> в md5() и вернул бы его. И unsigned_to_signed_char возьмет std::vector<unsigned char> и вернет std::string.)

...