- Случайные числа в Linux(RNG) или как «наполнить» /dev/random и /dev/urandom
- Как заполнить пул энтропии?
- Если нет аппаратной поддержки
- Havegd
- Тестирование
- rngd с /dev/urandom в качестве источника энтропии
- haveged
- Виртуальные машины
- /dev/random vs /dev/urandom and are they secure?
- Why machines can not generate true random number on its own?
- Why is generating a true random number is so important?
- Random Number Generator in Linux Kernels:
- /dev/random versus /dev/urandom versus /dev/arandom:
- Weaknesses in Linux Random Number Generators
- For Non-volatile Memory Hardware:
- Entropy Estimation:
- Concluding:
- About the author
- Usama Azad
- How to use /dev/random or urandom in C?
- 5 Answers 5
Случайные числа в Linux(RNG) или как «наполнить» /dev/random и /dev/urandom
Пожалуй всем пользователям Linux известны такие файлы псевдо-устройств как /dev/random и /dev/urandom. Эти устройства являются интерфейсом к генератору случайных чисел ядра(RNG, random number generator).
Случайные числа(они же — непредсказуемый набор битов) очень важны в криптографии. Они являются базовыми кирпичиками для криптографических протоколов. От качества (неповторимости, непредсказуемости) этих чисел зависит стойкость всевозможных TLS-сертификатов, SSH и GPG ключей, сессионных симметричных TLS-ключей и т.д. Так же случайные числа являются основой для генерации UUID’ов, PID’ов, TCP sequence numbers и многого другого.
RNG генерит случайные числа на основе данных из пула энтропии(entropy pool) в ядре Linux. Наполнением этого пула так же занимается RNG и делается это на основе случайных событий в системе таких как: тайминги клавиатуры и дисков, движения мыши, прерывания(interrupts), сетевой трафик.
Пул энтропии имеет фиксированный объем 4096 bits:
Размер пула нельзя изменить, это захардкожено в ядре.
Посмотреть текущий объем данных в пуле:
Доступный объем энтропии постоянно меняется, в зависимости от скорости пополнения и потребления соответственно.
Собственно через /dev/random и /dev/urandom приложения в user space получают эти самые случайные числаданные.
/dev/random является источником случайных данных наивысшего качества которые может предоставить ядро. Но при этом он блокирующийся, что означает, что приложение читающее из /dev/random повиснет в ожидании данных если пул энтропии окажется пустым.
/dev/urandom — unlimited random, не блокирующийся и приложения могут читать из него бесконечно. Предоставляет случайные данные такого же высокого качества что и /dev/random но до тех пор пока пул энтропии не опустеет. Когда пул будет пустым, /dev/urandom продолжит выдавать случайные данные но теоретически сильно меньшего качества.
Настоятельно рекомендуется для любых долго-живущих ключей, например для TLS-сертификатов использовать /dev/random т.к. только он гарантирует качество случайных чисел. Но, большинство приложений таких как Apache, Nginx, sshd и о Боже ssh-keygen, openssl используют /dev/urandom. Тут в принципе понятно Apache, Nginx, sshd не хотят блокироваться при генерации сессионных ключей. Но то, что ssh-keygen и openssl используют по умолчанию /dev/urandom меня поразило. Причем для openssl можно задать устройство при генерации ключей(ниже пример) а вот для ssh-keygen я возможности переопределить поведение не нашел.
В общем не важно откуда читают ваши приложения, нельзя допускать опустошение этого самого пула энтропии и тогда счастье будет и с /dev/urandom.
Прежде чем начать “майнить” энтропию, пара слов о ее корректном использовании из man /dev/random:
The amount of seed material required to generate a cryptographic key equals the effective key size of the key. For example, a 3072-bit RSA or Diffie-Hellman private key has an effective key size of 128 bits (it requires about 2^128 operations to break) so a key generator only needs 128 bits (16 bytes) of seed material from /dev/random.
Например openssl для генерации RSA ключа длиной 10240 bit использует всего 2048 исходного материала из /dev/random:
Как заполнить пул энтропии?
Лучшее решение это использование специальных аппаратных средств(TPM, Trusted Platform Module) или инструкций процессора типа RDRAND(есть в Intel IvyBridge и Haswell процессорах).
Проверить наличие подобных устройств на сервере поможет утилита rngd из пакета rng-tools
Если rngd обнаружит поддерживаемые средства то вам повезло и вы можете запустить сервис rngd. В моем случае их нет)
Собственно задача rngd читать энтропию из аппаратных средств и наполнять ей пул энтропии ядра. Делается это через специальный ioctl вызов(RNDADDENTROPY) интерфейса /dev/random.
Если нет аппаратной поддержки
В интернете можно встретить рекомендации, где предлагают указывать /dev/urandom как источник энтропии для rngd. То есть источником энтропии для ядра по сути будет само ядро). Это довольно сомнительная идея, и я бы не стал так делать и вам не советую. Но ради эксперимента я провел тесты и результаты(которые ниже) тоже довольно не плохие.
Havegd
В основе лежит алгоритм HAVAGE который генерирует энтропию на основе счётчиков и состояний процессора. В силу сложного, многоуровневого устройства процессоров, один и тот же код всегда выполняется за разное время и это не постоянство является основой для алгоритма HAVAGE.
На практике, это user space демон который как и rngd наполняет пул энтропии ядра через ioctl интерфейс /dev/random. при этом не нуждается в источнике энтропии как rngd.
Для centos пакет доступен из epel.
После установки нужно просто запустить сервис. С параметрами по умолчанию haveged будет стараться держать пул энтропии ядра на уровне не ниже 1024.
Тестирование
Без rngd и haveged, команда(ниже будет понятно, что она делает):
Не завершилась за сутки!
rngd с /dev/urandom в качестве источника энтропии
(то, что я вам не рекомендовал)
Тест(худший из 3-х результат):
Тут нужно смотреть на successes, failures, и на input channel speed.
При этом утилизация CPU процессом rngd: 57%
haveged
Тест(худший из 3-х результат):
При этом утилизация CPU процессом haveged:12%
Виртуальные машины
Не рекомендуется использовать haveged внутри ВМ, т.к. там вроде как счетчики CPU не такие точные(типа округляются) и это сказывается на качестве энтропии.
Тру путь это использовать virt-ioRNG(qemu-kvm) — паравиртуальное устройство которое будет брать энтропию из пула хоста. Но, это уже совсем другая история…)
Источник
/dev/random vs /dev/urandom and are they secure?
Who would have thought generating a random number would be such a mess, it is supposed to be just as straight-forward as guessing a number anywhere between a given range. But it is not as simple as it seems and also till now all the machines are proven to be unable to generate a true random number on its own.
Why machines can not generate true random number on its own?
Machines yet are just instructed sets of mechanisms and circuits, and hence they can not be instructed to think of a random number on its own without any help. And that’s why till now and further, we have been involving nature or humans with machines to generate a true random number. We will not discuss here how to generate a true random number but we will discuss about the already implemented random number generators and their working and weaknesses.
Why is generating a true random number is so important?
The question arises that why are generation of true random numbers important and the answer to that is because of security concerns. Most cryptographic algorithms are based upon the generation of random numbers as these random numbers are used to create cryptographic keys and if the random numbers generated are not truly random in nature, these make whole of those cryptographic techniques weaker and those keys can be predicted relatively easier using the algorithm that was used to generate those random keys. This is the most important reason for a true random numbers, other than applications like gambling.
Random Number Generator in Linux Kernels:
The topic for our discussion today is based upon Linux Random Number Generator, on what factors is this generator based on and is it really that random or is it just another typically unreliable random number.
Linux uses Pseudo Random Number Generator (PRNG) or Cryptographically Secure Pseudo Random Number Generator (CSPRNG) which means it uses complex mathematical formulas and environmental properties to achieve maximum randomness. Linux was the first OS to include PRNG in its kernel space. This was implemented by Theodore Ts’o in 1994.
Linux has three categories of random number generators, /dev/random, /dev/urandom, /dev/arandom. These all three are the files in which Linux stores random numbers. The random numbers in these files are generated using the environmental noise from the device drivers and other sources. Also, to ensure randomness in its random numbers, linux uses entropy which is the extent of uncertainty or disorder between them. You can also find the manual page for Linux Random Number Generator (RNG) here:
/dev/random versus /dev/urandom versus /dev/arandom:
The main differences between /dev/random, /dev/urandom and /dev/arandom is that /dev/random blocks if the entropy is not indicating sufficient randomness, /dev/urandom does not block ever, even when the pseudo random number generator is not fully seeded when booted and lastly /dev/arandom blocks only when pseudo random number generator is not yet fully seeded. In short, /dev/random is the safest of all, then comes /dev/arandom and the least safest is /dev/urandom. Normally /dev/random and /dev/urandom are used because /dev/arandom in many terms is similar to /dev/urandom. The entropy estimation for the random number pool in short is used to determine the randomness of numbers generated. The more entropy is, the more randomness is achieved and better it is. The current amount of entropy and size of its entropy pool are available at /proc/sys/kernel/random/ named as entropy_avail and pool_size, respectively, which can be displayed in terminal by using commands:
Both urandom and random are used in different scenarios. ‘Urandom’ is used where there is constant need of random numbers and its randomness is not much important while ‘random’ is used where there is a security concern and its randomness should be reliable as it blocks outputting random numbers if entropy is not up to the mark. Although entropy for urandom(Unlimited Random) is not much weaker but it is recommended to use random when more security is required because of the possibility of attacks on number generated by urandom.
Weaknesses in Linux Random Number Generators
For Non-volatile Memory Hardware:
For Linux kernels, the random number generator is not good for embedded hardware such as routers, in which bootable state is predictable and the source for enough entropy are limited. For this kind of hardware, it is recommended to save and use Random Number Generator (RNG) state before shutdown which will be used on the next boot. In such cases of routers, the attackers can only compromise and predict the generated random numbers if they have access to all the router links and they are eavesdropping on its communication links or if they have directly accessed the saved RNG state from the router itself.
For this flaw of RNG in case of hardware, third party entropy generators comes to the rescue. These entropy generators such as ‘haveged’ uses processor cache timing, external audio and video input devices to increase the entropy to an acceptable degree.
Entropy Estimation:
As mentioned before the Linux kernel determines randomness in terms of entropy but it does not actually calculate entropy each time and instead uses entropy estimations. Several researches have also revealed that the entropy estimation of random numbers used in Linux are not suitable or closer estimations, thus making the overall randomness of the numbers weaker.
Although there are some weaknesses in Linux Random Number Generator, but it is far better option compared to other RNGs, not to forget the ongoing patches that are provided by Linux contributors and developers.
Concluding:
This was all from my side about the Random Number Generator in Linux kernel. I had a good time in spreading this knowledge with you. Hope you learned something new through it and also that you will share the knowledge further to the world. Lastly, thanks for investing time in this article.
About the author
Usama Azad
A security enthusiast who loves Terminal and Open Source. My area of expertise is Python, Linux (Debian), Bash, Penetration testing, and Firewalls. I’m born and raised in Wazirabad, Pakistan and currently doing Undergraduation from National University of Science and Technology (NUST). On Twitter i go by @UsamaAzad14
Источник
How to use /dev/random or urandom in C?
I want to use /dev/random or /dev/urandom in C. How can I do it? I don’t know how can I handle them in C, if someone knows please tell me how. Thank you.
5 Answers 5
In general, it’s a better idea to avoid opening files to get random data, because of how many points of failure there are in the procedure.
On recent Linux distributions, the getrandom system call can be used to get crypto-secure random numbers, and it cannot fail if GRND_RANDOM is not specified as a flag and the read amount is at most 256 bytes.
As of October 2017, OpenBSD, Darwin and Linux (with -lbsd ) now all have an implementation of arc4random that is crypto-secure and that cannot fail. That makes it a very attractive option:
Otherwise, you can use the random devices as if they were files. You read from them and you get random data. I’m using open / read here, but fopen / fread would work just as well.
You may read many more random bytes before closing the file descriptor. /dev/urandom never blocks and always fills in as many bytes as you’ve requested, unless the system call is interrupted by a signal. It is considered cryptographically secure and should be your go-to random device.
/dev/random is more finicky. On most platforms, it can return fewer bytes than you’ve asked for and it can block if not enough bytes are available. This makes the error handling story more complex:
There are other accurate answers above. I needed to use a FILE* stream, though. Here’s what I did.
Just open the file for reading and then read data. In C++11 you may wish to use std::random_device which provides cross-platform access to such devices.
Zneak is 100% correct. Its also very common to read a buffer of random numbers that is slightly larger than what you’ll need on startup. You can then populate an array in memory, or write them to your own file for later re-use.
A typical implementation of the above:
This becomes more or less like a tape that just advances which can be magically replenished by another thread as needed. There are a lot of services that provide large file dumps of nothing but random numbers that are generated with much stronger generators such as:
- Radioactive decay
- Optical behavior (photons hitting a semi transparent mirror)
- Atmospheric noise (not as strong as the above)
- Farms of intoxicated monkeys typing on keyboards and moving mice (kidding)
Don’t use ‘pre-packaged’ entropy for cryptographic seeds, in case that doesn’t go without saying. Those sets are fine for simulations, not fine at all for generating keys and such.
Not being concerned with quality, if you need a lot of numbers for something like a monte carlo simulation, it’s much better to have them available in a way that will not cause read() to block.
However, remember, the randomness of a number is as deterministic as the complexity involved in generating it. /dev/random and /dev/urandom are convenient, but not as strong as using a HRNG (or downloading a large dump from a HRNG). Also worth noting that /dev/random refills via entropy, so it can block for quite a while depending on circumstances.
Источник