SHA - 程序输出不同于 sha512sum 命令
SHA - Output of program is different from sha512sum command
总而言之,我是第一次使用 openssl/sha.h 进行编程,编译时一切正常。这是我的代码:
#include <stdlib.h>
#include <stdio.h>
#include <openssl/sha.h>
int main()
{
int j;
FILE *hash_file = fopen("hash.txt", "wb");
for(j = 0; j < 256; j++)
{
unsigned char md[SHA512_DIGEST_LENGTH];
char* fileName = malloc(sizeof(int));
sprintf(fileName, "%X%s", j, ".txt");
int i;
FILE *file = fopen(fileName, "rb");
SHA512_CTX mdcontext;
int bytes;
unsigned char data[2048];
if(file == NULL)
{
printf("%s can not be opened\n", fileName);
return;
}
SHA512_Init(&mdcontext);
while((bytes = fread(data, 1, 2048, file) != 0))
SHA512_Update(&mdcontext, data, bytes);
SHA512_Final(md, &mdcontext);
for(i = 0; i < SHA512_DIGEST_LENGTH; i++)
{
printf("%x", md[i]);
fprintf(hash_file, "%x", md[i]);
}
// fprintf(hash_file, "\n");
printf("\n");
free(fileName);
fclose(file);
}
fclose(hash_file);
return 0;
}
我有这个输出:
711c22448e721e5491d8245b49425aa861f1fc4a15287f735e23799b65cffec5b5abdfddd91cd643aeb3b530d48f5e258e7e230a94ed525c1387bb4e1b
但是当我在 Linux 中使用 sha512sum 命令散列相同的文件时,我得到了这个输出:
6e3ea4bec3cd738f06f011c2f4ee4f6cd6d12205cafe41c083d52f94d9de4ab8b9e702664a367b633be14024a96e88a140a2e7fee4dc2c6e2f0bd436e281e35b make.sh
有什么问题?
天呐!
一个小小的括号可以让你拔出你的头发。
问题出在这条语句while((bytes = fread(data, 1, 2048, file) != 0))
。你看,在这个语句中 !=
条件将首先被评估。因此,当 fread
读取(和 returns)时,假设 n
个字符,它会检查是否 n!=0
。如果计算结果为 true
,则将 bytes
设置为 1
(true
转换为 1
)。
而现在,函数 SHA512_Update(&mdcontext, data, bytes);
变成了 SHA512_Update(&mdcontext, data, 1);
而它应该是 SHA512_Update(&mdcontext, data, n);
(其中 n
是成功读取的字符数)。
解决方案
将 while((bytes = fread(data, 1, 2048, file) != 0))
更改为 while((bytes = fread(data, 1, 2048, file)) != 0)
。
更新[将散列保存在char
数组中]:
SHA512
的输出是 128 个字符。因此,我们需要一个 char
数组,其大小是 SHA512_DIGEST_LENGTH
(64) 的两倍。然后,我们可以使用 sprintf
.
将其存储在 char
数组中
char hash[SHA512_DIGEST_LENGTH*2];
for(i = 0; i < SHA512_DIGEST_LENGTH; i++)
sprintf(&hash[i*2], "%02x", md[i]);
为什么i*2
?因为输出的宽度为 2 个字节。因此,结果将存储在 hash[i]
和 hash[i+1]
.
现在,打印它:
for(i = 0; i < SHA512_DIGEST_LENGTH*2; i++)
printf("%c", hash[i]);
PS:
了解 precedence。
并且不要忘记遵循您的 post 评论中的建议,尤其是史蒂夫关于使用 %02x
的建议。
总而言之,我是第一次使用 openssl/sha.h 进行编程,编译时一切正常。这是我的代码:
#include <stdlib.h>
#include <stdio.h>
#include <openssl/sha.h>
int main()
{
int j;
FILE *hash_file = fopen("hash.txt", "wb");
for(j = 0; j < 256; j++)
{
unsigned char md[SHA512_DIGEST_LENGTH];
char* fileName = malloc(sizeof(int));
sprintf(fileName, "%X%s", j, ".txt");
int i;
FILE *file = fopen(fileName, "rb");
SHA512_CTX mdcontext;
int bytes;
unsigned char data[2048];
if(file == NULL)
{
printf("%s can not be opened\n", fileName);
return;
}
SHA512_Init(&mdcontext);
while((bytes = fread(data, 1, 2048, file) != 0))
SHA512_Update(&mdcontext, data, bytes);
SHA512_Final(md, &mdcontext);
for(i = 0; i < SHA512_DIGEST_LENGTH; i++)
{
printf("%x", md[i]);
fprintf(hash_file, "%x", md[i]);
}
// fprintf(hash_file, "\n");
printf("\n");
free(fileName);
fclose(file);
}
fclose(hash_file);
return 0;
}
我有这个输出:
711c22448e721e5491d8245b49425aa861f1fc4a15287f735e23799b65cffec5b5abdfddd91cd643aeb3b530d48f5e258e7e230a94ed525c1387bb4e1b
但是当我在 Linux 中使用 sha512sum 命令散列相同的文件时,我得到了这个输出:
6e3ea4bec3cd738f06f011c2f4ee4f6cd6d12205cafe41c083d52f94d9de4ab8b9e702664a367b633be14024a96e88a140a2e7fee4dc2c6e2f0bd436e281e35b make.sh
有什么问题?
天呐!
一个小小的括号可以让你拔出你的头发。
问题出在这条语句while((bytes = fread(data, 1, 2048, file) != 0))
。你看,在这个语句中 !=
条件将首先被评估。因此,当 fread
读取(和 returns)时,假设 n
个字符,它会检查是否 n!=0
。如果计算结果为 true
,则将 bytes
设置为 1
(true
转换为 1
)。
而现在,函数 SHA512_Update(&mdcontext, data, bytes);
变成了 SHA512_Update(&mdcontext, data, 1);
而它应该是 SHA512_Update(&mdcontext, data, n);
(其中 n
是成功读取的字符数)。
解决方案
将 while((bytes = fread(data, 1, 2048, file) != 0))
更改为 while((bytes = fread(data, 1, 2048, file)) != 0)
。
更新[将散列保存在char
数组中]:
SHA512
的输出是 128 个字符。因此,我们需要一个 char
数组,其大小是 SHA512_DIGEST_LENGTH
(64) 的两倍。然后,我们可以使用 sprintf
.
char
数组中
char hash[SHA512_DIGEST_LENGTH*2];
for(i = 0; i < SHA512_DIGEST_LENGTH; i++)
sprintf(&hash[i*2], "%02x", md[i]);
为什么i*2
?因为输出的宽度为 2 个字节。因此,结果将存储在 hash[i]
和 hash[i+1]
.
现在,打印它:
for(i = 0; i < SHA512_DIGEST_LENGTH*2; i++)
printf("%c", hash[i]);
PS: 了解 precedence。
并且不要忘记遵循您的 post 评论中的建议,尤其是史蒂夫关于使用 %02x
的建议。