2012-09-03 95 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