比较C中的unsigned char数组

时间:2012-09-03 12:04:14

标签: c function pointers openssl

这是我程序的输出:

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 中的比较不起作用?
我做错了什么?

2 个答案:

答案 0 :(得分: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);

所以你需要转换到另一个。然后比较。

答案 1 :(得分:1)

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

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

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

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

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

  1. 在比较
  2. 之前,将读取的哈希值转换为二进制
  3. 在比较之前将运行时计算的哈希值转换为文本
  4. 你可以看到这两种解决方案是彼此的补充,这对我来说似乎很自然。我不鼓励您在评论中提到的解决方案,涉及临时文件。

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

    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;