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

機能しない理由は、16 進値を含む ASCII 文字列へのポインタであるためです。もう1つはバイナリ値の配列です(16進数として印刷しています)。

....
// 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か?

また、ハッシュの読み込みを適切に処理しているかどうかもわかりません。ファイルに16進文字の長い文字列がある場合は、比較する前にバイナリに変換する必要があります。SHA256によって計算されるハッシュは、16進文字列ではなく、2進です。

これを修正するための2つの(私の意見では)合理的な方法があります:

  1. 比較する前に、ファイルから読み取ったハッシュをバイナリに変換します
  2. 比較する前に、実行時に計算されたハッシュをテキストに変換します

2つのソリューションがお互いを補完し合っていることがわかります。これは、私には当然のことのようです。コメントで言及した一時ファイルを含む解決策はお勧めしません。

上記のうち、2番目のものはおそらく実装が最も簡単です。逆の場合よりもバイトの束を16進数に変換する方が簡単だからです。それは私が行く解決策であり、次のようなものです。

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()、16進数でハッシュを取得するために呼び出すことができます。

一般的な観察として、これを行わないでください:

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 に答える