2016-06-21 23 views
-1

stdinから読み取られた文字列のSHA-256を計算するプログラムを作成しています。 私のプログラムにopenssl/sha.hが提供する機能を使用しています。私は "普通のハッシュ"と "塩漬けのハッシュ"を実装しました。sizeofまたはstrlenで入力を測定するかどうかによって、SHA-256ハッシュが異なる

ノーマルハッシュ

私は言葉をハッシュした場合passwordは、私は次の出力を得る:シェルコマンドの出力で見られるように、正しい

SHA256_Update(&sha256, string, strlen(string)) --> 5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8 
SHA256_Update(&sha256, string, sizeof(string)) --> 5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8 

echo -n "password" | sha256sum --> 5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8 

塩漬けハッシュ

は、それから* 2000 13として計算され、26000(塩が常に同じであることを考慮

complete = salt + string 

を得る、別の文字列(塩)の後に入力された文字列を連結し、塩漬けハッシュを実装しようとしました)、私はシェルコマンドに一致する出力を期待:strlen(complete)を使用して

echo -n "26000password" | sha256sum --> c9bcf6ab867bdff7bf2223407c6a391f5c475fb411f7eae08fb361a671d4fd0d 

は私に正しい答えを与える:

SHA256_Update(&sha256, complete, strlen(complete)) --> c9bcf6ab867bdff7bf2223407c6a391f5c475fb411f7eae08fb361a671d4fd0d 

しかし、sizeof(complete)を使用して私に異なる答えを与える:

SHA256_Update(&sha256, complete, sizeof(complete)) --> ef73eaf729a0601f9d99ed0a11ef82ae82ca74042de5a724889f82e4f6e59bb0 

だから私は二つの問題があります。

  1. を第二の場合は、(私は推測sizeof代わりにstrlenの使用である間違って何かを持っていますしかし、それはなぜ2番目の問題があるのか​​説明していないので、私はいくつかの「一貫性のない状態」について考えています。
  2. プログラムをもう一度実行すると、プログラムを停止して実行するたびに間違ったハッシュが変わってしまいます。

だから、問題はstrlenの代わりにsizeofを使用していると仮定します。私はがそのデータ型を格納するために使用されるバイト数を返すことを知っているので(ポインタは4バイトになります)、strlenは文字列の長さを返しますが、 2番目のケース。

コードの抜粋

#include <openssl/sha.h> 
#define MAX_LENGTH 1024 

unsigned long salt; 

// Salted //////////////////////////////// 
void compute_sha256_with_sizeof_complete(const char *string, char *sha) 
{ 
    int i; 
    char temp[65]; 
    char complete[MAX_LENGTH]; 
    char salt_str[MAX_LENGTH]; 
    unsigned char hash[SHA256_DIGEST_LENGTH]; 
    SHA256_CTX sha256; 

    /* complete = salt_str + string */ 
    if (sprintf(salt_str, "%lu", salt) < 0) 
     error_handler("compute_sha256 | sprintf"); 
    if (strcpy(complete, salt_str) == NULL) 
     error_handler("compute_sha256 | strcpy"); 
    if (strcat(complete, string) == NULL) 
     error_handler("compute_sha256 | strcat"); 

    /* compute sha256 of 'complete' */ 
    if (SHA256_Init(&sha256) == 0) 
     error_handler("compute_sha256 | SHA256_Init"); 
    if (SHA256_Update(&sha256, complete, sizeof(complete)) == 0) 
     error_handler("compute_sha256 | SHA256_Update"); 
    if (SHA256_Final(hash, &sha256) == 0) 
     error_handler("compute_sha256 | SHA256_Final"); 
    for (i = 0; i < SHA256_DIGEST_LENGTH; i++) 
     if ((sprintf(temp + (i * 2), "%02x", hash[i])) < 0) 
      error_handler("compute_sha256 | sprintf"); 

    temp[64] = 0; 

    if (strcpy(sha, temp) == NULL) 
     error_handler("compute_sha256 | strcpy"); 

    printf("SHA256 (sizeof_complete):\t%s\n", sha); 
} 

void compute_sha256_with_strlen_complete(const char *string, char *sha) 
{ 
    int i; 
    char temp[65]; 
    char complete[MAX_LENGTH]; 
    char salt_str[MAX_LENGTH]; 
    unsigned char hash[SHA256_DIGEST_LENGTH]; 
    SHA256_CTX sha256; 

    /* complete = salt_str + string */ 
    if (sprintf(salt_str, "%lu", salt) < 0) 
     error_handler("compute_sha256 | sprintf"); 
    if (strcpy(complete, salt_str) == NULL) 
     error_handler("compute_sha256 | strcpy"); 
    if (strcat(complete, string) == NULL) 
     error_handler("compute_sha256 | strcat"); 

    /* compute sha256 of 'complete' */ 
    if (SHA256_Init(&sha256) == 0) 
     error_handler("compute_sha256 | SHA256_Init"); 
    if (SHA256_Update(&sha256, complete, strlen(complete)) == 0) 
     error_handler("compute_sha256 | SHA256_Update"); 
    if (SHA256_Final(hash, &sha256) == 0) 
     error_handler("compute_sha256 | SHA256_Final"); 
    for (i = 0; i < SHA256_DIGEST_LENGTH; i++) 
     if ((sprintf(temp + (i * 2), "%02x", hash[i])) < 0) 
      error_handler("compute_sha256 | sprintf"); 

    temp[64] = 0; 

    if (strcpy(sha, temp) == NULL) 
     error_handler("compute_sha256 | strcpy"); 

    printf("SHA256 (strlen_complete):\t%s\n", sha); 
} 

// Normal //////////////////////////////// 

void compute_sha256_with_sizeof_string(const char *string, char *sha) 
{ 
    int i; 
    char temp[65]; 
    char complete[MAX_LENGTH]; 
    char salt_str[MAX_LENGTH]; 
    unsigned char hash[SHA256_DIGEST_LENGTH]; 
    SHA256_CTX sha256; 

    /* complete = salt_str + string */ 
    if (sprintf(salt_str, "%lu", salt) < 0) 
     error_handler("compute_sha256 | sprintf"); 
    if (strcpy(complete, salt_str) == NULL) 
     error_handler("compute_sha256 | strcpy"); 
    if (strcat(complete, string) == NULL) 
     error_handler("compute_sha256 | strcat"); 

    /* compute sha256 of 'string' */ 
    if (SHA256_Init(&sha256) == 0) 
     error_handler("compute_sha256 | SHA256_Init"); 
    if (SHA256_Update(&sha256, string, sizeof(string)) == 0) 
     error_handler("compute_sha256 | SHA256_Update"); 
    if (SHA256_Final(hash, &sha256) == 0) 
     error_handler("compute_sha256 | SHA256_Final"); 
    for (i = 0; i < SHA256_DIGEST_LENGTH; i++) 
     if ((sprintf(temp + (i * 2), "%02x", hash[i])) < 0) 
      error_handler("compute_sha256 | sprintf"); 

    temp[64] = 0; 

    if (strcpy(sha, temp) == NULL) 
     error_handler("compute_sha256 | strcpy"); 

    printf("SHA256 (sizeof_string):\t\t%s\n", sha); 
} 

void compute_sha256_with_strlen_string(const char *string, char *sha) 
{ 
    int i; 
    char temp[65]; 
    char complete[MAX_LENGTH]; 
    char salt_str[MAX_LENGTH]; 
    unsigned char hash[SHA256_DIGEST_LENGTH]; 
    SHA256_CTX sha256; 

    /* complete = salt_str + string */ 
    if (sprintf(salt_str, "%lu", salt) < 0) 
     error_handler("compute_sha256 | sprintf"); 
    if (strcpy(complete, salt_str) == NULL) 
     error_handler("compute_sha256 | strcpy"); 
    if (strcat(complete, string) == NULL) 
     error_handler("compute_sha256 | strcat"); 

    /* compute sha256 of 'string' */ 
    if (SHA256_Init(&sha256) == 0) 
     error_handler("compute_sha256 | SHA256_Init"); 
    if (SHA256_Update(&sha256, string, strlen(string)) == 0) 
     error_handler("compute_sha256 | SHA256_Update"); 
    if (SHA256_Final(hash, &sha256) == 0) 
     error_handler("compute_sha256 | SHA256_Final"); 
    for (i = 0; i < SHA256_DIGEST_LENGTH; i++) 
     if ((sprintf(temp + (i * 2), "%02x", hash[i])) < 0) 
      error_handler("compute_sha256 | sprintf"); 

    temp[64] = 0; 

    if (strcpy(sha, temp) == NULL) 
     error_handler("compute_sha256 | strcpy"); 

    printf("SHA256 (strlen_string):\t\t%s\n", sha); 
} 

void match_password(const char *line) 
{ 
    char hash[MAX_LENGTH]; 
    salt *= 13; 

    compute_sha256_with_strlen_complete(line, hash); 
    compute_sha256_with_sizeof_complete(line, hash); 
    compute_sha256_with_strlen_string(line, hash); 
    compute_sha256_with_sizeof_string(line, hash); 
} 

void read_password_from_stdin(void) 
{ 
    char line[MAX_LENGTH]; 
    salt = 2000; 

    printf("> "); 

    if (fgets(line, MAX_LENGTH, stdin) == NULL) 
     error_handler("read_password_from_stdin | fgets"); 
    if (line[strlen(line)-1] == '\n') 
     line[strlen(line)-1] = '\0'; 

    match_password(line); 
} 

int main(int argc, char **argv) 
{ 
    if (argc != 1) 
    { 
     fprintf(stderr, "Usage: %s <no arguments>\n", argv[0]); 
     return EXIT_FAILURE; 
    } 

    while (!feof(stdin)) 
     read_password_from_stdin(); 

    return EXIT_SUCCESS; 
} 

答えて

0

sizeof(complete)は、completesalt_strは、そのスタックに割り当てられたローカル変数であり、関数が実行を開始したときに任意のコンテンツを有していてもよく、常にMAX_LENGTH、または1024 compute_sha256_with_sizeof_completeでありますコンパイラに依存します。completeに少なくともいくつかの0以外の値があり、strcpystrcatは、塩ストリング、またはstdinから読み取ったものがMAX_LENGTH文字でない限り、それらの値に置き換わることはありません。したがって、入れたデータのSHA-256だけでなく、compute_sha256_with_sizeof_completeが実行を開始すると、ランダムなデータがcompleteにあります。

sizeof_completeの出力が毎回変わる理由は、スタックに残っているランダムなデータ、したがってcompleteのランダムなデータが、プログラムが実行されるたびに異なることがあるからです。明示的に初期化するには、char complete[MAX_LENGTH] = {0};と言うことができますが、この状況ではsizeofを使用しないほうがよいでしょう:)。

対照的に、strlenを使用すると、終了するNULL文字までの文字列の内容のみをハッシュします。 strcpystrcatは、予想通りに文字列のその部分を埋めます。そのため、期待した結果が得られます。 strlenは間違いなく正しい選択です。 (そして、あなたがコーディングしている間、added protection against memory issuesのために代わりstrcpystrcatstrncpystrncatを使用しています。)

1

sizeofを使用して、completeMAX_LENGTHのオクテットすなわち)のすべてのオクテットの代わりにのみ有用オクテットにSHAを計算します。

completeは初期化されていないため、コンテンツは何でもかまいません。 sprintfを使用すると、strcatstrcpyは文字列を含むパーツのみを初期化するので、配列の終わりは未だ初期化されていません。毎回同じハッシュを持つようにするには、complete

char complete[MAX_LENGTH] = { 0 }; 
関連する問題