0

所以我正在尝试编写自己的“keccaksum”程序,除了运行

for i in {1..50}; do ./keccaksum 256 test.o; done

输出

4d4cc035e544cd4837b45550094dd3c419e380af3b0c74109c00053c7ed82040  test.o

大多数时候和

b19d21947b7228da366b4d26f232b87e21999ff1a220c37c9bed6553260068c0  test.o

一些时间。

这里的相关功能是

void printsum(const char *_fname, FILE *_f, size_t size){   
    uint64_t state[25];
    uint8_t *hash = malloc(size * sizeof(uint8_t));
    uint8_t buf[25];
    uint8_t tmp[144];
    register int i, rsize, rsizew;
    register size_t j;

    rsize = 200 - 2 * size;
    rsizew = rsize / 8;

    //Clear the state
    memset(state, 0, sizeof(state));

    while(1) {
        //read up to rsize bytes, then do work
        j = fread(buf, 1, rsize, _f);

        //check some stuff
        if(feof(_f)){
            break;
        } else if(ferror(_f)){
            fprintf(stderr, "Error when reading %s.\n", _fname);
            goto fin;
        } else {
            //First few blocks (i.e. not last block)
            for(i = 0; i < rsizew; i++)
                state[i] ^= ((uint64_t *)buf)[i];
            keccakf(state, KECCAK_ROUNDS);
        }
    }

    //Last block + padding
    memcpy(tmp, buf, j);
    tmp[j++] = 1;
    memset(tmp + j, 0, rsize - j);
    tmp[rsize - 1] |= 0x80;

    for(i = 0; i < rsizew; i++)
        state[i] ^= ((uint64_t *)tmp)[i];
    keccakf(state, KECCAK_ROUNDS);

    //copy hash
    memcpy(hash, state, size);

    //print
    for(i = 0; i < size; i++) printf("%02x", hash[i]);
    printf("  %s\n", _fname);

fin:    
    if(_f != stdin) fclose(_f);
    free(hash);
}

这让我相信这段代码的某些部分是未定义的,我不知道什么可能是未定义的。

4

1 回答 1

1

首先替换这个:

if(feof(_f)){
        break;
    } else if(ferror(_f)){
        fprintf(stderr, "Error when reading %s.\n", _fname);
        goto fin;
    } else {
        for(i = 0; .....

有了这个:

if ( j < rsize )
    break;

for (i = 0; .......

如果您关心要显示哪个错误消息,您可以ferror在循环后检查。

接下来,这可能会导致未定义的行为,具体取决于系统的对齐要求:

state[i] ^= ((uint64_t *)buf)[i];

为了安全起见,您可以将其替换为:

{
    uint64_t temp;
    memcpy(&temp, buf + i * sizeof temp, sizeof temp);
    state[i] ^= temp;
}

但是,如果您的系统是 little-endian,我不清楚这是否是 keccak 算法的正确行为;size在不是 的精确倍数的情况下,这也不是正确的8

对于 的某些值,可能会出现各种其他错误size。您没有指定size导致问题的值,从而使事情变得困难。如果您更新您的帖子以显示完整的程序,这将非常有帮助。(即其他人可以原封不动地编译以重现问题的东西)。同时:

如果size > 100那样的话,这将变得混乱。

对于较小的值,size这是缓冲区溢出:

uint8_t tmp[144];
memcpy(tmp, buf, j);
tmp[j++] = 1;
memset(tmp + j, 0, rsize - j);
tmp[rsize - 1] |= 0x80;

因为rsize可能最多200,这将溢出tmp。另外,考虑一下是否要在 case 中执行这个块j == 0

在这一行memcpy(hash, state, size);中,您操作的字节数是 很奇怪rsizew * 8,但是您复制的字节数是size,这些通常不会相同。

在您发布完整程序后,我会更新我的帖子,以考虑size使用中的实际值。

注意。这应该是SHA-3吗?

于 2014-06-02T04:42:05.210 回答