我正在编写一个程序来计算从stdin
读取的字符串的SHA-256。
我正在使用openssl/sha.h
提供的功能进入我的程序。我实现了#34;普通哈希"和#34;盐渍哈希"。
正常哈希
如果我对单词password
进行哈希,我会得到以下输出:
SHA256_Update(&sha256, string, strlen(string)) --> 5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8
SHA256_Update(&sha256, string, sizeof(string)) --> 5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8
这是正确的,如shell命令
的输出所示echo -n "password" | sha256sum --> 5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8
咸味哈希
然后我尝试实现 salted hash ,将输入字符串连接到另一个字符串(salt)之后,获取
complete = salt + string
鉴于salt总是相同的(26000
,计算为13 * 2000),我期望输出匹配shell命令:
echo -n "26000password" | sha256sum --> c9bcf6ab867bdff7bf2223407c6a391f5c475fb411f7eae08fb361a671d4fd0d
使用strlen(complete)
给出正确答案:
SHA256_Update(&sha256, complete, strlen(complete)) --> c9bcf6ab867bdff7bf2223407c6a391f5c475fb411f7eae08fb361a671d4fd0d
然而,使用sizeof(complete)
给出了不同的答案:
SHA256_Update(&sha256, complete, sizeof(complete)) --> ef73eaf729a0601f9d99ed0a11ef82ae82ca74042de5a724889f82e4f6e59bb0
所以我有两个问题:
sizeof
代替strlen
,但这并不能解释为什么我遇到第二个问题,所以我是考虑一些"记忆的不一致状态"); 所以我认为问题在于使用sizeof
而不是strlen
。我知道sizeof
返回用于存储该数据类型的字节数(因此指针将是4个字节),而strlen
将给出字符串的长度,但我不知道'}我明白为什么我只在第二种情况下得到错误。
代码摘录
#include <openssl/sha.h>
#define MAX_LENGTH 1024
unsigned long salt;
// Salted ////////////////////////////////
void compute_sha256_with_sizeof_complete(const char *string, char *sha)
{
int i;
char temp[65];
char complete[MAX_LENGTH];
char salt_str[MAX_LENGTH];
unsigned char hash[SHA256_DIGEST_LENGTH];
SHA256_CTX sha256;
/* complete = salt_str + string */
if (sprintf(salt_str, "%lu", salt) < 0)
error_handler("compute_sha256 | sprintf");
if (strcpy(complete, salt_str) == NULL)
error_handler("compute_sha256 | strcpy");
if (strcat(complete, string) == NULL)
error_handler("compute_sha256 | strcat");
/* compute sha256 of 'complete' */
if (SHA256_Init(&sha256) == 0)
error_handler("compute_sha256 | SHA256_Init");
if (SHA256_Update(&sha256, complete, sizeof(complete)) == 0)
error_handler("compute_sha256 | SHA256_Update");
if (SHA256_Final(hash, &sha256) == 0)
error_handler("compute_sha256 | SHA256_Final");
for (i = 0; i < SHA256_DIGEST_LENGTH; i++)
if ((sprintf(temp + (i * 2), "%02x", hash[i])) < 0)
error_handler("compute_sha256 | sprintf");
temp[64] = 0;
if (strcpy(sha, temp) == NULL)
error_handler("compute_sha256 | strcpy");
printf("SHA256 (sizeof_complete):\t%s\n", sha);
}
void compute_sha256_with_strlen_complete(const char *string, char *sha)
{
int i;
char temp[65];
char complete[MAX_LENGTH];
char salt_str[MAX_LENGTH];
unsigned char hash[SHA256_DIGEST_LENGTH];
SHA256_CTX sha256;
/* complete = salt_str + string */
if (sprintf(salt_str, "%lu", salt) < 0)
error_handler("compute_sha256 | sprintf");
if (strcpy(complete, salt_str) == NULL)
error_handler("compute_sha256 | strcpy");
if (strcat(complete, string) == NULL)
error_handler("compute_sha256 | strcat");
/* compute sha256 of 'complete' */
if (SHA256_Init(&sha256) == 0)
error_handler("compute_sha256 | SHA256_Init");
if (SHA256_Update(&sha256, complete, strlen(complete)) == 0)
error_handler("compute_sha256 | SHA256_Update");
if (SHA256_Final(hash, &sha256) == 0)
error_handler("compute_sha256 | SHA256_Final");
for (i = 0; i < SHA256_DIGEST_LENGTH; i++)
if ((sprintf(temp + (i * 2), "%02x", hash[i])) < 0)
error_handler("compute_sha256 | sprintf");
temp[64] = 0;
if (strcpy(sha, temp) == NULL)
error_handler("compute_sha256 | strcpy");
printf("SHA256 (strlen_complete):\t%s\n", sha);
}
// Normal ////////////////////////////////
void compute_sha256_with_sizeof_string(const char *string, char *sha)
{
int i;
char temp[65];
char complete[MAX_LENGTH];
char salt_str[MAX_LENGTH];
unsigned char hash[SHA256_DIGEST_LENGTH];
SHA256_CTX sha256;
/* complete = salt_str + string */
if (sprintf(salt_str, "%lu", salt) < 0)
error_handler("compute_sha256 | sprintf");
if (strcpy(complete, salt_str) == NULL)
error_handler("compute_sha256 | strcpy");
if (strcat(complete, string) == NULL)
error_handler("compute_sha256 | strcat");
/* compute sha256 of 'string' */
if (SHA256_Init(&sha256) == 0)
error_handler("compute_sha256 | SHA256_Init");
if (SHA256_Update(&sha256, string, sizeof(string)) == 0)
error_handler("compute_sha256 | SHA256_Update");
if (SHA256_Final(hash, &sha256) == 0)
error_handler("compute_sha256 | SHA256_Final");
for (i = 0; i < SHA256_DIGEST_LENGTH; i++)
if ((sprintf(temp + (i * 2), "%02x", hash[i])) < 0)
error_handler("compute_sha256 | sprintf");
temp[64] = 0;
if (strcpy(sha, temp) == NULL)
error_handler("compute_sha256 | strcpy");
printf("SHA256 (sizeof_string):\t\t%s\n", sha);
}
void compute_sha256_with_strlen_string(const char *string, char *sha)
{
int i;
char temp[65];
char complete[MAX_LENGTH];
char salt_str[MAX_LENGTH];
unsigned char hash[SHA256_DIGEST_LENGTH];
SHA256_CTX sha256;
/* complete = salt_str + string */
if (sprintf(salt_str, "%lu", salt) < 0)
error_handler("compute_sha256 | sprintf");
if (strcpy(complete, salt_str) == NULL)
error_handler("compute_sha256 | strcpy");
if (strcat(complete, string) == NULL)
error_handler("compute_sha256 | strcat");
/* compute sha256 of 'string' */
if (SHA256_Init(&sha256) == 0)
error_handler("compute_sha256 | SHA256_Init");
if (SHA256_Update(&sha256, string, strlen(string)) == 0)
error_handler("compute_sha256 | SHA256_Update");
if (SHA256_Final(hash, &sha256) == 0)
error_handler("compute_sha256 | SHA256_Final");
for (i = 0; i < SHA256_DIGEST_LENGTH; i++)
if ((sprintf(temp + (i * 2), "%02x", hash[i])) < 0)
error_handler("compute_sha256 | sprintf");
temp[64] = 0;
if (strcpy(sha, temp) == NULL)
error_handler("compute_sha256 | strcpy");
printf("SHA256 (strlen_string):\t\t%s\n", sha);
}
void match_password(const char *line)
{
char hash[MAX_LENGTH];
salt *= 13;
compute_sha256_with_strlen_complete(line, hash);
compute_sha256_with_sizeof_complete(line, hash);
compute_sha256_with_strlen_string(line, hash);
compute_sha256_with_sizeof_string(line, hash);
}
void read_password_from_stdin(void)
{
char line[MAX_LENGTH];
salt = 2000;
printf("> ");
if (fgets(line, MAX_LENGTH, stdin) == NULL)
error_handler("read_password_from_stdin | fgets");
if (line[strlen(line)-1] == '\n')
line[strlen(line)-1] = '\0';
match_password(line);
}
int main(int argc, char **argv)
{
if (argc != 1)
{
fprintf(stderr, "Usage: %s <no arguments>\n", argv[0]);
return EXIT_FAILURE;
}
while (!feof(stdin))
read_password_from_stdin();
return EXIT_SUCCESS;
}
答案 0 :(得分:1)
使用sizeof
,您可以在complete
的每个八位字节上计算sha(即<{1}}八位字节上的),而只是在有用的八位字节上计算。
MAX_LENGTH
未初始化,因此内容可以是任何内容,每次发布时都不同。使用complete
,sprintf
和strcat
仅初始化包含字符串的部分,因此数组的结尾仍然未初始化。要每次都使用相同的哈希值,请初始化strcpy
:
complete
答案 1 :(得分:0)
sizeof(complete)
始终为MAX_LENGTH
或1024.在compute_sha256_with_sizeof_complete
中,complete
和salt_str
是局部变量,因此在堆栈上分配,可能有函数开始运行时的任何内容,具体取决于编译器。我猜想complete
中至少有一些非零值,strcpy
和strcat
除非是盐字符串,或者你从{{1}读取的内容,否则不会替换这些值},字符长stdin
。因此,您不仅要获取所放入数据的SHA-256,还要获取MAX_LENGTH
开始运行时complete
中随机数据的所有数据。
这也是每次compute_sha256_with_sizeof_complete
输出更改的原因:每次程序运行时,堆栈中留下的随机数据(因此在sizeof_complete
中)可能会有所不同。要明确初始化它,您可以说complete
,但最好不要在这种情况下使用char complete[MAX_LENGTH] = {0};
:)。
相比之下,使用sizeof
仅对字符串内容进行哈希处理,直至终止NULL字符。 strlen
和strcpy
按预期填充字符串的那一部分,这就是您获得预期结果的原因。 strcat
绝对是正确的选择。 (在进行编码时,请使用strlen
和strncpy
代替strncat
和strcpy
added protection against memory issues。)