Я понятия не имею, что может быть прослушано

Поэтому я пытаюсь написать свою собственную программу "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 ответ

Прежде всего замените это:

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;
}

Однако мне не ясно, является ли это правильным поведением для алгоритма 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?

Другие вопросы по тегам