2012-09-03 60 views
0

这是我的程序的输出:比较无符号的字符数组用C

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; 
} 

为什么我里面的功能比较哈希PWD没有按”工作?
我做错了什么?

+0

查看[strncmp](http://linux.die.net/man/3/strncmp)和[memcmp](http://linux.die.net/man/3/memcmp)。 – Sjoerd

+2

太多的线条,你是否可以将它缩小一点,以显示错误? –

+0

@Fredrik完成:) – polslinux

回答

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); 

所以,你需要或者转换为其他。然后比较。

+0

谢谢:)但我怎么能转换的东西是比其他更大(或更低)? – polslinux

+0

好吧,我已经解决了; D谢谢你! – polslinux

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; 
} 

调用上面的指针大到足以容纳字符串版本的缓冲区,然后比较,对从文件加载的一个。

UPDATE:或者,您可以使用现有的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; 
+0

我敢肯定,因为在添加散列功能之前,文件只有“USERNAME CLEAR_PASSWORD”,并且所有工作都完美! – polslinux

+0

不适用于memcmp :( – polslinux

+0

)您应该添加'printf()':s打印出'strcmp()'之前的'tmp'和'u'字符串以及散列检查器中的'retval'。 – unwind