0

我尝试自己在 C 中实现 SHA1 算法,主要是为了学习一些东西。我使用RFC 3174作为指南。但它根本不起作用,因为我得到了错误的哈希值。例如,“秘密”应该给出“e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4”,但我得到“484991f4d4c04d90a904698cb0f726d01941c7”。即使对于空字符串,我也会得到错误的哈希值。如果有人可以解释我做错了什么,那就太好了。这是我的代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>

#define LE2BE64(a) \
a = ((a>>56)&0xff) | ((a>>40)&0xff00) | ((a>>24)&0xff0000) | ((a>>8)&0xff000000) | \
((a<<8)&0xff00000000) | ((a<<24)&0xff0000000000) | ((a<<40)&0xff000000000000) | \
((a<<56)&0xff00000000000000)

#define cycleWord(a, n) \
((a << n) | (a >> (32 - n)))

#define f0(B, C, D) \
((B & C) | ((~B) & D))

#define f13(B, C, D) \
(B ^ C ^ D)

#define f2(B, C, D)\
((B & C) | (B & D) | (C & D))

#define K0 0x5A827999
#define K1 0x6ED9EBA1
#define K2 0x8F1BBCDC
#define K3 0xCA62C1D6


uint32_t H0 = 0x67452301;
uint32_t H1 = 0xEFCDAB89;
uint32_t H2 = 0x98BADCFE;
uint32_t H3 = 0x10325476;
uint32_t H4 = 0xC3D2E1F0;

void padMessage(char *buf, uint64_t buflen) {
    uint64_t msg_len = strlen(buf);
    buf[msg_len] = 0x80;

    if((msg_len + 1) % 64 < 56) {
        for(int i = 0; i < 56 - (msg_len + 1); i++) {
            buf[msg_len + 1 + i] = 0x00;
        }
    } else {
        for(int i = 0; 1; i++) {
            buf[msg_len + 1 + i] = 0x00;
            if((msg_len + 2 + i) % 64 == 0)
                break;
        }
        for(int i = 64; buflen - i < buflen - 9; i--) {
            buf[buflen - i] = 0x00;
        }
    }

    LE2BE64(msg_len);
    memcpy(&buf[buflen - 8], &msg_len, 8);
}

void processBlock(unsigned char block[64]) {
    uint32_t W[80] = { 0 };
    uint32_t A, B, C, D, E, TEMP;

    for(int t = 0; t < 16; t++) {
        W[t] |= (uint32_t)block[t * 4];
        W[t] |= ((((uint32_t)block[t * 4 + 1])<<8)&0xff00);
        W[t] |= ((((uint32_t)block[t * 4 + 2])<<16)&0xff0000);
        W[t] |= ((((uint32_t)block[t * 4 + 3])<<24)&0xff000000);
    }

    for(int t = 16; t < 80; t++) {
        W[t] = cycleWord(W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16], 1);
    }

    A = H0;
    B = H1;
    C = H2;
    D = H3;
    E = H4;

    for(int t = 0; t < 20; t++) {
        TEMP = cycleWord(A, 5) + f0(B, C, D) + E + W[t] + K0;
        E = D;
        D = C;
        C = cycleWord(B, 30);
        B = A;
        A = TEMP;
    }    

    for(int t = 20; t < 40; t++) {
        TEMP = cycleWord(A, 5) + f13(B, C, D) + E + W[t] + K1;
        E = D;
        D = C;
        C = cycleWord(B, 30);
        B = A;
        A = TEMP;
    }    

    for(int t = 40; t < 60; t++) {
        TEMP = cycleWord(A, 5) + f2(B, C, D) + E + W[t] + K2;
        E = D;
        D = C;
        C = cycleWord(B, 30);
        B = A;
        A = TEMP;
    }    

    for(int t = 60; t < 80; t++) {
        TEMP = cycleWord(A, 5) + f13(B, C, D) + E + W[t] + K3;
        E = D;
        D = C;
        C = cycleWord(B, 30);
        B = A;
        A = TEMP;
    }    

    H0 = H0 + A;
    H1 = H1 + B;
    H2 = H2 + C;
    H3 = H3 + D;
    H4 = H4 + E;
}

void main(int argc, char *argv[]) {
    char *cmd_str;
    uint64_t buflen;
    if(argc < 2) {
        buflen = 0;
        cmd_str = calloc(buflen + 1, sizeof(char));
        cmd_str = "";
    } else {
        buflen = strlen(argv[1]);
        cmd_str = argv[1];
    }

    if(buflen % 64 < 56) {
        buflen = ((buflen / 64) + 1) * 64;
    } else {
        buflen = ((buflen / 64) + 2) * 64;
    }
    unsigned char *buffer = calloc(buflen, sizeof(unsigned char));
    strcpy(buffer, cmd_str);
    padMessage(buffer, buflen);

    unsigned char tmp[64];
    for(uint64_t i = 0; i < buflen / 64; i++) {
        memcpy(tmp, &buffer[i * 64], 64);
        processBlock(tmp);
    }
    
    printf("%x%x%x%x%x\n", H0, H1, H2, H3, H4);
}
4

0 回答 0