我不知道什么可能被窃听

时间:2014-06-02 03:46:10

标签: c undefined keccak

所以我试着写自己的" 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);
}

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

1 个答案:

答案 0 :(得分: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。另外,考虑是否要在j == 0

的情况下执行此块

在这一行memcpy(hash, state, size);中,你操作的字节数是rsizew * 8是奇怪的,但是你复制的字节数是size,这些一般不一样

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

NB。这应该是SHA-3吗?