Это вопрос о реализации ядра Linux /dev/urandom
.Если пользователь просит прочитать очень большой объем данных (гигабайт) и энтропия не добавляется в пул, если возможно предсказать следующие данные, сгенерированные из urandom, на основе текущих данных?
Обычный случай - это когдаэнтропия часто добавляется в пул, но в моем случае мы можем считать, что никакой дополнительной энтропии не было (например, добавление ее было отключено патчем ядра).Так что в моем случае вопрос касается самого алгоритма urandom.
Источник - /drivers/char/random.c или http://www.google.com/codesearch#KMCRKdMbI4g/drivers/char/random.c&q=urandom%20linux&type=cs&l=116
или http://lxr.linux.no/linux+v3.3.3/drivers/char/random.c
// data copying loop
while (nbytes) {
extract_buf(r, tmp);
memcpy(buf, tmp, i);
nbytes -= i;
buf += i;
ret += i;
}
static void extract_buf(struct entropy_store *r, __u8 *out)
{
int i;
__u32 hash[5], workspace[SHA_WORKSPACE_WORDS];
__u8 extract[64];
/* Generate a hash across the pool, 16 words (512 bits) at a time */
sha_init(hash);
for (i = 0; i < r->poolinfo->poolwords; i += 16)
sha_transform(hash, (__u8 *)(r->pool + i), workspace);
/*
* We mix the hash back into the pool to prevent backtracking
* attacks (where the attacker knows the state of the pool
* plus the current outputs, and attempts to find previous
* ouputs), unless the hash function can be inverted. By
* mixing at least a SHA1 worth of hash data back, we make
* brute-forcing the feedback as hard as brute-forcing the
* hash.
*/
mix_pool_bytes_extract(r, hash, sizeof(hash), extract);
/*
* To avoid duplicates, we atomically extract a portion of the
* pool while mixing, and hash one final time.
*/
sha_transform(hash, extract, workspace);
memset(extract, 0, sizeof(extract));
memset(workspace, 0, sizeof(workspace));
/*
* In case the hash function has some recognizable output
* pattern, we fold it in half. Thus, we always feed back
* twice as much data as we output.
*/
hash[0] ^= hash[3];
hash[1] ^= hash[4];
hash[2] ^= rol32(hash[2], 16);
memcpy(out, hash, EXTRACT_SIZE);
memset(hash, 0, sizeof(hash));
}
Существует механизм предотвращения возврата, но как насчет «прямого следа»?
Например: я выполнил однократный системный вызов чтения для 500 МБ из urandom, и все данные до 200-го МБ были известны, и нетдополнительная энтропия в пуле, могу ли я предсказать, каким будет 201-й мегабайт?