2011-10-21 72 views
8

Tôi đang cố gắng để viết một hàm C sử dụng OpenSSL/libcrypto để tính toán tổng SHA256 của một tập tin. Tôi đang dựa vào mã của tôi trên ví dụ C++ của Adam Lamer là here.Tính và in SHA256 băm của một tập tin sử dụng OpenSSL

Dưới đây là mã của tôi:

int main (int argc, char** argv) 
{ 
    char calc_hash[65]; 

    calc_sha256("file.txt", calc_hash); 
} 

int calc_sha256 (char* path, char output[65]) 
{ 
    FILE* file = fopen(path, "rb"); 
    if(!file) return -1; 

    char hash[SHA256_DIGEST_LENGTH]; 
    SHA256_CTX sha256; 
    SHA256_Init(&sha256); 
    const int bufSize = 32768; 
    char* buffer = malloc(bufSize); 
    int bytesRead = 0; 
    if(!buffer) return -1; 
    while((bytesRead = fread(buffer, 1, bufSize, file))) 
    { 
     SHA256_Update(&sha256, buffer, bytesRead); 
    } 
    SHA256_Final(hash, &sha256); 

    sha256_hash_string(hash, output); 
    fclose(file); 
    free(buffer); 
    return 0; 
}  

void sha256_hash_string (char hash[SHA256_DIGEST_LENGTH], char outputBuffer[65]) 
{ 
    int i = 0; 

    for(i = 0; i < SHA256_DIGEST_LENGTH; i++) 
    { 
     sprintf(outputBuffer + (i * 2), "%02x", hash[i]); 
    } 

    outputBuffer[64] = 0; 
} 

Vấn đề là đây .... hãy nhìn vào số tiền tính dưới đây cho một ví dụ file:

Known good SHA256: 6da032d0f859191f3ec46a89860694c61e65460d54f2f6760b033fa416b73866 
Calc. by my code: 6dff32ffff59191f3eff6affff06ffff1e65460d54ffff760b033fff16ff3866 

Tôi cũng nhận * chồng đập phát hiện * khi mã được thực thi xong.

Có ai thấy những gì tôi đang làm sai?

Cảm ơn!

+0

Tôi có mẫu kê khai. – dan6470

+0

Tại sao const int bufSize được cố định với kích thước 32768? nó có thể là nhiều hơn hoặc ít hơn –

Trả lời

12

Hình như có rất nhiều '0xff' khối trong đầu ra của bạn, và các khối tương ứng trong chuỗi tốt có tập bit cao ... có thể là một vấn đề mở rộng dấu đâu đó.

Liệu làm:

char hash[SHA256_DIGEST_LENGTH]; 

unsigned, như:

unsigned char hash[SHA256_DIGEST_LENGTH]; 

giúp đỡ? (Đặc biệt là chữ ký của sha256_hash_string.)

+0

Điều đó cố định nó! Cảm ơn bạn! Tôi đang sử dụng Ubuntu bằng gcc. – dan6470

+1

bình luận của tôi về ít endianess đã sai, vì vậy tôi đã xóa nó ... Adam đã có lời giải thích đúng về 8 byte được in mỗi khi đầu vào là tiêu cực. Đây là một ví dụ tốt về lý do tại sao, khi giao dịch với "byte" và không phải "ký tự chuỗi", bạn nên sử dụng 'unsigned char' (hoặc uint8 hoặc một trong các biến thể của nó). Các 'char' trần nên được dành riêng cho các ký tự ASCII. –

11

Bạn đang in ra đã kýchar làm số nguyên. Nếu byte là số âm, nó được chuyển đổi thành signed int (các quảng cáo đối số mặc định trong cuộc gọi đến sprintf), sau đó được chuyển đổi thành unsigned int (thông qua định dạng số %x) và in ra.

Vì vậy, byte A0 là -96 là byte đã ký, được chuyển thành -96 thành signed int, là 0xFFFFFFA0 trong hex, vì vậy nó được in ra dưới dạng FFFFFFA0.

Để sửa lỗi này, trường hợp từng byte một unsigned char trước khi in:

sprintf(..., (unsigned char)hash[i]); 

Bạn đang gặp cảnh báo về chồng đập vì có một byte ký ở cuối băm, vì vậy bạn đang viết 8 byte FFFFFFB7 tại offset 58 khi bạn dự định chỉ viết 2 byte. Điều này dẫn đến một buffer overflow, mà xảy ra được phát hiện ở đây bởi vì trình biên dịch có thể chèn một khu vực bảo vệ an ninh hoặc cookie trong ngăn xếp trước khi giá trị trả về, và nó phát hiện ra rằng đó khu vực bảo vệ được vô tình sửa đổi.

+0

Vậy đó! Cảm ơn vì đã giải thích !! – dan6470

Các vấn đề liên quan