【问题标题】:I have no idea what could possibly be bugged我不知道什么可能被窃听
【发布时间】:2014-06-02 03:46:09
【问题描述】:

所以我正在尝试编写自己的“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);
}

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

【问题讨论】:

  • 你确定rsize &lt;= 25
  • (200 - 2 * size) / 8 &lt;= 25...
  • 请注意,您正在使用rsizew = rsize / 8 并使用rsize 读取缓冲区。
  • rsize = 200 - 2 * size 应该是真的
  • 只需检查它并确保它是真实的。并尽可能使用 valgrind。

标签: c undefined keccak


【解决方案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 &gt; 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的情况下是否要执行这个block。

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-04-10
    • 1970-01-01
    • 2015-11-21
    • 1970-01-01
    • 2015-01-13
    • 2019-04-20
    • 1970-01-01
    相关资源
    最近更新 更多