Результат хэширования sha512 в C отличается от других языков (php, python)

Я впервые пишу код на языке C. У меня проблема с sha512. Результат не совпадает с другими языками (php, python).

Моя цель — использовать sha512 для шифрования строкового цикла больше раз. Но первый и второй раз то же самое с Python или PHP, но начать с третьего, это было по-другому.

Результат изображения:
введите описание изображения здесь

Запустить на Linux.

Вот мой код:

С

$ gcc test.c -lcrypto -o test

$ ./test

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

char *hash_sha512(char *data) {
SHA512_CTX ctx;
char *md = malloc(sizeof(char)*(SHA512_DIGEST_LENGTH+1));
SHA512_Init(&ctx);
SHA512_Update(&ctx, data, strlen(data));
SHA512_Final(md, &ctx);
md[SHA512_DIGEST_LENGTH] = '\0';

return md;
}

int main(void) {

char *str = hash_sha512("123456");
FILE *fp;
int count = 10;

fp = fopen("/tmp/c.txt", "w+");
do {
fputs(str, fp);
fputs("\n", fp);
str = hash_sha512(str);
} while (--count);

fclose(fp);

return 0;
}

PHP

<?php
$password='123456';
$hash = hash('sha512', $password, TRUE);
$i = 10;
do {
file_put_contents('/tmp/php.txt',$hash . "\n", FILE_APPEND);
$hash = hash('sha512', $hash, TRUE);
} while (--$i);

питон

#! /usr/bin/env python

import hashlib
password='123456'
count = 10
f = open('/tmp/python.txt','a')
pass_hash = hashlib.sha512(password).digest()
for _ in range(count):
f.write(pass_hash)
pass_hash = hashlib.sha512(pass_hash).digest()
f.close()

2

Решение

Вы не сравниваете яблоки с яблоками, и в процессе также неправильно вычисляете свой дайджест для своего кода C. Поток байтов, генерируемый дайджестом sha512, не является C-строкой, и помещение нулевого символа в конец магическим образом не делает его единым целым. Например, первый дайджест выглядит так (в шестнадцатеричном формате):

ba 32 53 87 6a ed 6b c2 2d 4a 6f f5 3d 84 06 c6
ad 86 41 95 ed 14 4a b5 c8 76 21 b6 c2 33 b5 48
ba ea e6 95 6d f3 46 ec 8c 17 f5 ea 10 f3 5e e3
cb c5 14 79 7e d7 dd d3 14 54 64 e2 a0 ba b4 13

Второй сборник:

73 14 8c 26 3f fc 49 86 34 cc 1e be bd 67 51 69
97 01 11 69 a3 7e 28 11 ed 51 d5 2c 82 d4 d5 72
af 32 c2 31 13 9f 1d 0f d7 af e2 9e 44 1d 44 ae
fa 29 c1 85 5e c6 52 07 63 92 72 11 0d 19 56 74

и третье, это:

a5 b2 65 20 84 63 58 8b 56 c1 08 4c 37 03 c4 a1
a9 0c 71 05 89 cb 09 fc 22 07 85 8f 64 3b b1 72
8b 3e f3 f3 06 2c 84 72 f8 3a c6 1f f9 47 87 b8
b8 00 3d 73 0b 29 a3 7b 88 a9 e3 14 ee 19 06 f7

Вы видите это? Посмотрите на последний набор октетов. Последний ряд, второй байт.

b8 00 3d 73 0b 29 a3 7b 88 a9 e3 14 ee 19 06 f7
^^

Так как длина вашего источника дайджеста ошибочно основана на длине строки C, именно здесь она обрезается. Остальные байты игнорируются, и ваша цепочка дайджеста навсегда ошибочна.

Кроме того, ваш код пропускает память, как сито пропускает дождевую воду. Вероятно, нет ничего сложного для 640 байтов и 10 итераций, но перенесите это на миллион итераций, и оно начнет складываться. Поместите его в критически важный программный продукт, и это совершенно неприемлемо. Учти это:

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

void hash_sha512(unsigned char const *src, size_t len, unsigned char *dst)
{
SHA512_CTX ctx;
SHA512_Init(&ctx);
SHA512_Update(&ctx, src, len);
SHA512_Final(dst, &ctx);
}

int main(void)
{
char pwd[] = "123456"unsigned char digest[2][SHA512_DIGEST_LENGTH] = {{0}};
hash_sha512((unsigned char*)pwd, strlen(pwd), digest[0]);

unsigned int count=1;
for (; count<10; ++count)
{
hash_sha512(digest[(count-1)%2], SHA512_DIGEST_LENGTH, digest[count%2]);
}

return 0;
}

Это решает проблему, описанную ранее, и окончательный дайджест будет в digest[(count-1)%2]Я оставляю вам возможность интегрировать ваш файловый ввод-вывод. Ниже приведены первые 10 итераций с использованием начального пароля "123456" для вашей справки. Я предлагаю вам использовать hexdump чтобы убедиться, что все идет по плану.

Десять итераций

ba 32 53 87 6a ed 6b c2 2d 4a 6f f5 3d 84 06 c6
ad 86 41 95 ed 14 4a b5 c8 76 21 b6 c2 33 b5 48
ba ea e6 95 6d f3 46 ec 8c 17 f5 ea 10 f3 5e e3
cb c5 14 79 7e d7 dd d3 14 54 64 e2 a0 ba b4 13

73 14 8c 26 3f fc 49 86 34 cc 1e be bd 67 51 69
97 01 11 69 a3 7e 28 11 ed 51 d5 2c 82 d4 d5 72
af 32 c2 31 13 9f 1d 0f d7 af e2 9e 44 1d 44 ae
fa 29 c1 85 5e c6 52 07 63 92 72 11 0d 19 56 74

a5 b2 65 20 84 63 58 8b 56 c1 08 4c 37 03 c4 a1
a9 0c 71 05 89 cb 09 fc 22 07 85 8f 64 3b b1 72
8b 3e f3 f3 06 2c 84 72 f8 3a c6 1f f9 47 87 b8
b8 00 3d 73 0b 29 a3 7b 88 a9 e3 14 ee 19 06 f7

75 15 b6 cb ef 3e 0b 4a 35 e3 58 b9 8b bb a3 2d
a0 bd 1e c8 9d 32 23 7c 09 ae c0 a7 f7 4e 70 35
c8 34 dd 2a ac 8d e4 e9 d1 e8 b5 7a 80 d8 80 db
07 7c 28 18 e8 30 40 aa 06 85 a5 2a 63 41 c6 b7

4d 25 d3 24 5e 22 b1 e4 e4 3f 1e a4 4e a3 eb e4
89 ab e3 c2 63 56 01 17 ea 1f 85 58 d4 da d2 63
6d 9c 2f 74 39 b6 87 85 2c 1c 27 f8 a8 9d 2a cf
ee 64 1c d9 28 5d 88 e5 c7 8b 9f 6e 1e c8 dd 99

17 e2 7f 2f fd a7 c3 b7 41 73 b9 2d e7 61 6e 77
72 79 41 16 14 90 01 db 6f 66 3b e6 12 94 22 06
a9 91 14 55 ab 7f 3a 34 eb 12 b3 a9 78 69 6a 23
8e 82 13 46 1e ed b4 33 e8 74 f8 15 15 a3 19 57

c1 60 9e c9 c4 82 4f 1c 71 a7 e2 7c 6e fc d9 5b
63 4f 27 25 ec fe d2 58 d6 77 61 8f 93 a1 a4 1e
f0 b7 8a 24 36 91 40 9b 5f dd c3 b5 b9 e1 c6 97
24 66 89 b0 79 c2 84 05 8e 4f 43 4b 5a bb 53 e6

7b f9 4c 45 be 2f 29 68 80 36 79 b7 1a 79 36 a3
7e 8b 9f 6e a0 80 3a 9e 5c bc 27 39 bd 2e 6e 9f
5a b2 8c b9 7f 43 9f b2 c4 72 41 99 f7 65 71 26
b7 b8 06 24 a8 34 ea 69 e4 05 ab 55 a7 a8 32 c2

1a 28 09 ee c5 a4 e5 86 98 0f 52 a1 fd ff a6 14
0f 3f 8b 14 85 34 bd a6 bd 45 54 2e 4c 2b da 62
d0 7c 98 38 5c 98 cd 76 df 18 ca 36 16 f2 be 8e
6c ed 76 e8 28 39 e6 38 d7 41 a4 9e 31 6d f0 ab

ce 0c 0f 2e 89 e5 1d c3 58 88 a3 1f a6 7c 18 74
1a 20 d3 84 43 9c 3a e8 4b d9 f1 fe 2e a1 67 0b
62 62 2d dc 02 eb 82 cd 90 b2 0f 8f e2 fe f5 43
7a ad 0c b1 62 d7 e9 45 3f be 14 53 2e b6 d0 68
1

Другие решения

Спасибо за @WhozCraig.

Вот мой окончательный код.

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

int main(void) {
char pwd[] = "123456";
unsigned char digest[2][SHA512_DIGEST_LENGTH] = {{0}};
SHA512((unsigned char*)pwd, strlen(pwd), digest[0]);

unsigned int count = 1;
for (; count<10; ++count) {
SHA512(digest[(count-1)%2], SHA512_DIGEST_LENGTH, digest[count%2]);
}

unsigned char result[SHA512_DIGEST_LENGTH * 2 + 1];
unsigned int i = 0;
for(; i < SHA512_DIGEST_LENGTH; i++) {
sprintf(&result[i*2], "%02x", digest[(count-1)%2][i]);
}
printf("The result is %s.\n", result);

return 0;
}
1

По вопросам рекламы [email protected]