-
Notifications
You must be signed in to change notification settings - Fork 284
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add cryptographically secure random number generator #352
Conversation
{ | ||
private import std.stdio; | ||
|
||
//ссылка на файловый поток |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not really a good idea to keep comments in russian in public project ;)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, forgot to delete this.
A few observations:
Sorry for the nitpicking, but going towards a stable version, the quality bar needs to be set very high. |
It runs too slow and blocks application. Just try to run unit tests a few times, I am sure, you'll see a 30-60 sec pause after 3-5 run. It isn't acceptable for responsive application. Use /dev/random only for long-term secure-critical purposes like SSL/SSH keys, random passwords or salts for ciphers.
I allocate memory only once at the constructor. It lets to full the all buffer via only one system call. Yes, it's possible to return ubyte instead of an array, but it will require a lot of system calls, and context switching is expensive. So, any ideas?
It's OK. I'll fix the code style. |
I see, so it seems like /dev/urandom is usually the same as /dev/random, just without enforcing minimum entropy requirements for the entropy pool, right? Then it probably indeed makes sense to use it by default. However, this brings up another issue, probably only important for /dev/random: Since the file access may block, it needs to be implemented in terms of a
Sorry, I've overlooked that. The problem here is that it imposes the risk of accidentally using the wrong random value when someone stores the slice returned by |
Not exactly. As I know, /dev/random is hardware-based random number generator with high entropy level and minimum entropy requirements. Since in computer not so much random events it works slow.
I think we have no problems with /dev/urandom. Time to generate 100_000_000 bytes (100 bytes in the buffer, 1_000_000 iterations) is 6.041 sec (~60 nanoseconds per byte). I think it's fast enough, and non-blocking API can only delay generation.
I document it:
Is it clear?
It's possible, but will work slower. The basic idea is: create new |
The Wikipedia article about /dev/(u)random is a bit fuzzy, but it seemed to imply that both use the same pool of hardware random noise to seed their PRNG, which the difference that /dev/random will block until the noise pool fulfills certain entropy requirements. Removing /dev/random for now would work, too, then.
In your benchmark, which compiler flags did you use and did you compare it against the |
Yes, /dev/random and /dev/urandom use the same hardware random noise. Also, /dev/urandom use PRNG to generate random numbers faster and hardware random noise to seed and re-seed the PRNG, but /dev/random use only hardware random noise.
I did not compare it, just to buffers with different size. I use DMD without any flags (sorry, forgot about it), so optimized program should be faster.
OK, convinced. Idea: we can add
So, we should just remove |
@s-ludwig: Do you agree to have |
Let's keep both possibilities. Having an input range interface can come in very handy and won't have a big performance overhead (at least in release mode) and the |
I think it will be better to have
the function |
The structs should either implement But I don't get why you are against an |
OK, I'll see what can we do. |
Yes, input range API works normally with
It's possible, I agree. But in that case we can have security issue. We should store |
That does not make sense. Programmer is always supposed to use |
Yes, I know. But it's still possible. |
As well as dereferencing null. |
Additional question: how will be use |
But you'll see the error message. |
You could use Regarding the Something like |
Not exactly. |
The same can be achieved by using separate RNG instances. It's just offset by one level. |
Additional notice: |
If someone has found an exploit to access internal program state remotely, we have much more serious issue than some compromised sessions. It really seems like you are over-thinking this. Those who care about the security are perfectly aware of all risks and pitfalls. Those who don't won't be using this RNG directly at all and should never even know about its existence. Using power tools blindly and getting your leg shut off is expected behaviour. |
I don't know, if someone has compromised the application in that way, it will most likely be possible to start much worse attacks than reading the cached random bytes. And for critical things I'd always use something like the hash based RNG with a high factor and the buffer should always be much smaller in comparison. But yes, in theory this cache imposes an additional risk. But the most important step is to get away from the current implementation, which is using a buffer AND returns a view to it. |
Don't worry, path is ready. @s-ludwig, your example will be look like this:
Please tell me the function name that you want to have in API: |
Probably. But if bug not a critical, bad guy can't run any code, but theoretically can do something else. I just put attention to this. |
It doesn't give additional security. If I know init state and algorithm I can calculate result myself. So, hash based RNG secured only if nobody else knows init state. |
I'd choose Thinking about
But how would you know the init state? You just know a small part of the buffer used to calculate a single hash value + for all I've read about /dev/urandom it is not a simple PRNG with a fixed init state. If you could simply calculate the next random numbers by knowing a few, you could also calculate the next session ID after receiving one. |
OK, in that case I just rename method. |
Actually, speaking about ranges, it may be the case where using OutputRange API makes much more sense. |
Do you have any usage example? |
Method was renamed. Please tell me if everything OK with API. In that case I'll fix the code style issues. |
It is a matter of simply turning (possibly |
@ilya-stromberg: Looks good so far. In anticipation of a common base class/interface for multiple RNGs, I would maybe replace the "Rand" suffix with "RNG" or the full "RandomNumberGenerator" (but this is borderline in length). BTW you have removed the hash based RNG. Didn't that work out with the new interface? Anyway, it's not important for the session stuff, so it can be added when needed. @Dicebot: However, that is much less useful than an input range in terms of processing the data stream and would again require a temporary buffer. |
OK, I'll add "RNG" suffix.
I just didn't have time to port it to the new API. Also, I don't want remodel it few times. So, I'll try to implement it when we finish API design. |
Thank you for idea, I didn't think about it. |
The suffix was replaced. Do you have any additional wishes? |
No, the API so far should be fine. Thank you for making the adjustments. |
Added hash-based RNG. |
AFAICS mainly just the DOC comments and the pragma is missing. |
OK, will do. |
Maybe |
Thanks for idea. |
Fix DDoc comments and pragma. BTW, what's wrong with pragma and WinRT? |
Thanks, looks good to merge. The problem with the pragma is that linking against "advapi" is not allowed for WinRT applications. So it would actually be necessary to write proper replacement code for that, but since the WinRT back end is still in its infancy, that can be safely postponed. |
Add cryptographically secure random number generator
Supports Windows and Posix
Tested on Windows and Linux, but should work also on OS X and FreeBSD.