所以我试着写自己的" 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);
}
这让我相信这段代码的某些部分是未定义的,我不知道什么可能是未定义的。
答案 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吗?