0

这是我的程序的输出:

Username: paolo
Password: paolo
254835d73cc88095a30fc74133beabe9d8463b2954493227b205ea326c8a9c86
254835d73cc88095a30fc74133beabe9d8463b2954493227b205ea326c8a9c86
No user or password inside the database;

这是我的程序:

int main(void){

    int isok = -1;
    char *user = NULL, *pass = NULL;

    printf("Username: ");
    if(scanf("%m[^\n]%*c", &user) == EOF){
        perror("scanf user");
        return EXIT_FAILURE;
    }

    printf("Password: ");
    if(scanf("%m[^\n]%*c", &pass) == EOF){
        perror("scanf");
        free(user);
        return EXIT_FAILURE;
    }

    isok = check_login(user, pass);
    if(isok == 0){
        /* some code here */
    }
    else{
        /* some code here */
    }
    return EXIT_SUCCESS;
}

int check_login(char *u, char *p){

    int retval = -1;
    FILE *fp = NULL;
    char *tmp, *tmp2, *line = NULL;

    /* some code here */

    while(fgets(line, 255, fp) != NULL){
        tmp = strtok(line, " ");
        if(tmp == NULL){
            perror("strtok 1");
            free(u);
            free(p);
            free(line);
            free(fp);
            return -1;
        }

        tmp2 = strtok(NULL, "\n"); 
        if(tmp2 == NULL){
            perror("strtok 2");
            free(u);
            free(p);
            free(line);
            free(fp);
            return -1;
        }
        retval = hash_pwd(p, (unsigned char *)tmp2);
        if((strcmp(tmp,u) == 0) && (retval == 0)){
            free(line);
            free(fp);
            return 0;
        }
        else{
            continue;
        }
    }
    return -1;
}


int hash_pwd(char *to_hash, unsigned char *tocheck){
    SHA256_CTX context;
    unsigned char md[SHA256_DIGEST_LENGTH];
    size_t length = strlen((const char*)to_hash);
    int i;
    SHA256_Init(&context);
    SHA256_Update(&context, (unsigned char*)to_hash, length);
    SHA256_Final(md, &context);
    for(i=0; i<SHA256_DIGEST_LENGTH; i++){
        printf("%02x", md[i]);
    }
    printf("\n%s\n", tocheck);
    for(i=0; i<SHA256_DIGEST_LENGTH; i++){
        if(md[i] == tocheck[i]) continue;
        else return 1;
    }
    return 0;
}

为什么我在函数hash-pwd中的比较不起作用?
我究竟做错了什么?

4

2 回答 2

4

它不起作用的原因是一个指向包含十六进制值的 ascii 字符串的指针;另一个是二进制值数组(您打印为十六进制)。

....
// print out the digest - a binary array of SHA256_DIGEST_LENGTH
// bytes printed in hex
for(i=0; i<SHA256_DIGEST_LENGTH; i++){
    printf("%02x", md[i]);
}

// A string of SHA256_DIGEST_LENGTH *2 + 1 length - containing
// the value in hex spelled out in ascii.
printf("\n%s\n", tocheck);

因此,您需要将其中一个转换为另一个。然后比较。

于 2012-09-03T12:35:53.887 回答
1

你怎么知道哈希比较失败了?它也可能是strcmp()电话:

if((strcmp(tmp,u) == 0) && (retval == 0)){

例如,您确定tmp不包含缺少的换行符u吗?

此外,不确定您是否正确处理了哈希加载,如果文件中有一长串十六进制字符,则需要在比较之前将其转换为二进制。SHA256 计算的哈希是二进制的,而不是十六进制字符串。

有两种(在我看来)解决这个问题的合理方法:

  1. 在比较之前将从文件读取的哈希转换为二进制
  2. 在比较之前将运行时计算的哈希转换为文本

您可以看到这两种解决方案是互为补充的,这对我来说似乎很自然。我不鼓励您在评论中提到的涉及临时文件的解决方案。

在上面,第二个可能是最容易实现的,因为将一堆字节转换为十六进制比反过来更容易。这是我会采用的解决方案,例如:

static int hash_to_string(char *output, size_t output_max,
                           const unsigned char *hash, size_t hash_size)
{
  size_t i;

  if(output_max < 2 * hash_size + 1)
    return 0;
  for(i = 0; i < hash_size; ++i)
    sprintf(output + 2 * i, "%02x", hash[i] & 0xff);
  output[2 * i] = '\0';
  return 1;
}

使用指向足够大以保存字符串版本的缓冲区的指针调用上述方法,然后将其与从文件加载的缓冲区进行比较。

更新:或者,您可以使用现有的 API 并调用SHA256_End()以获取十六进制的哈希。

作为一般观察,不要这样做:

for(i=0; i<SHA256_DIGEST_LENGTH; i++){
    if(md[i] == tocheck[i]) continue;
    else return 1;
}
return 0;

相反,这样做:

return memcmp(md, tocheck, sizeof md) != 0;
于 2012-09-03T12:06:46.563 回答