Обработка загадочного вывода при печати массива байтов в C - PullRequest
1 голос
/ 12 мая 2019

Недавно я столкнулся с проблемой написанного мной сценария.

#include "md5.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

char* hashfunc (char* word1, char* word2){

    MD5_CTX md5;
    MD5_Init(&md5);
    char * word = (char *) malloc(strlen(word1)+ strlen(word2) );
    strcpy(word,word1);
    strcat(word,word2);
    MD5_Update(&md5,word,strlen(word));
    unsigned char* digest = malloc(sizeof(char)* 16); //MD5 generates 128bit hashes, each char has 4 bit, 128/4 = 32
    MD5_Final(digest,&md5);
    return digest;
}

int main(int argc, char* argv[]){
    char* a = argv[1];
    char* b = argv[2];

    unsigned char* ret = hashfunc(a,b);
    printf("%s\n",ret);
    printf("%i\n",sizeof(ret));
}

Поскольку хэш-функция возвращает массив неподписанных символов, я подумал, что напечатаю это как есть.
К сожалению, мой вывод следующий:
. @ A% Ćw0
который согласно sizeof() имеет длину 8 байт.
Как мне преобразовать это в читаемый формат?

Заранее спасибо!

PS:
Вывод должен выглядеть так:

1c0143c6ac7505c8866d10270a480dec

Ответы [ 2 ]

4 голосов
/ 12 мая 2019

Во-первых, sizeof указатель даст размер указателя char, который является размером слова в вашей машине (я полагаю, это 64-разрядный код, поскольку ваш размер вернул 8). Указатели не несут информацию о размере указателя, вам придется возвращать ее в другом месте.

В любом случае, поскольку вы знаете, что дайджест MD5 имеет 16 байтов, вы можете просто перебирать каждый из них и печатать каждый байт в более читаемом формате, используя sprintf. Примерно так:

for (int i = 0; i < 16; i++)
    printf("%02x", (int)(unsigned char)digest[i]);
putchar('\n');

Если вы хотите распечатать его в файл, измените printf на fprintf и putchar на fputc (однако аргументы немного меняются).

Чтобы поместить его в строку, вам нужно sprint каждый байт в правильной позиции строки, что-то вроде этого:

char* str = malloc(33 * sizeof(char));
for (int i = 0; i < 16; i++)
    sprintf(str+2*i, "%02x", (int)(unsigned char)digest[i]);

P.S: не забудьте free все после.

4 голосов
/ 12 мая 2019

Нет гарантии, что ваш hashfunc будет производить печатаемые строки ASCII. Теоретически, поскольку они на самом деле являются просто двоичными данными, они могут иметь встроенные 0, которые в любом случае испортят все обычные функции обработки строк.

Лучше всего печатать каждый беззнаковый символ как беззнаковый символ через цикл for.

void printhash(unsigned char* hash)
{
    for(int i = 0; i < 16; i++)
    {
        printf("%02x", hash[i]);
    }
    printf("\n");
}
...