> Le 26 sept. 2017 à 07:31, Xiaodi Wu via swift-evolution > <swift-evolution@swift.org> a écrit : > > * The distinction to be made here is CSPRNGs versus non-cryptographically > secure PRNGs, where CSPRNG : PRNG. “Reproducible” is not the right word. > Based on my understanding, some CSPRNGs can be “reproducible” if the seed is > known; what makes it cryptographically secure is that observing its previous > *outputs* does not provide information useful to predict future outputs. > Along those lines, it may be important to securely delete the seed from > memory as soon as possible; there is some way of doing so in C (it’s used in > the ChaCha20 reference implementation) but I don’t believe any way of doing > so in Swift.
It's possible to use a CSPRNG-grade algorithm and seed it once to get a reproducible sequence, but when you use it as a CSPRNG, you typically feed entropy back into it at nondeterministic points to ensure that even if you started with a bad seed, you'll eventually get to an alright state. Unless you keep track of when entropy was mixed in and what the values were, you'll never get a reproducible CSPRNG. We would give developers a false sense of security if we provided them with CSPRNG-grade algorithms that we called CSPRNGs and that they could seed themselves. Just because it says "crypto-secure" in the name doesn't mean that it'll be crypto-secure if it's seeded with time(). Therefore, "reproducible" vs "non-reproducible" looks like a good distinction to me. > * On the issue of consuming entropy: a glaring underlying inconvenience in > the API needs to be reckoned with. Sometimes, there simply isn’t enough > entropy to generate another random number. If cryptographic security were not > default, then it might be OK to fall back to some other method that produces > a low-quality result. However, if we are to do the secure thing, we must > decide whether the lack of entropy results in a call to a random method to > (a) return nil; (b) throw; (c) fatalError; or (d) block. There is no way to > paper over this problem; not enough entropy means you can’t get a random > number when you want it. The debate over blocking versus non-blocking error, > for example, held up the addition of getrandom() to Glibc for some time. In > my proposed design, initializing a PRNG from the system’s secure stream of > random bytes is failable; therefore, a user can choose how to handle the lack > of entropy. However, it is desirable to have a thread-local CSPRNG that is > used for calls, say, to Int.random(). It would be unfortunate if Int.random() > itself was failable; however, that leads to an uncomfortable question: if > there is insufficient entropy, should Int.random() block or fatalError? That > seems pretty terrible too. However, one cannot simply write this off as an > edge case: if this is to be a robust part of the standard library, it must do > the “right” thing. Particularly if Swift is to be a true systems programming > language and it must accommodate the case when a system is first booted and > there is very little entropy. That's not really the case anymore these days. You're probably thinking of /dev/urandom vs. /dev/random. On Darwin, they're the same thing and never run out (see man urandom). On Linux, the state of the art is that you leave /dev/random alone. Don't take it from me, Prof. Daniel J. Bernstein <https://en.wikipedia.org/wiki/Daniel_J._Bernstein> wrote this <https://www.mail-archive.com/cryptography@randombit.net/msg04763.html> a while ago: > Think about this for a moment: whoever wrote the /dev/random manual page > seems to simultaneously believe that > > (1) we can't figure out how to deterministically expand one 256-bit > /dev/random output into an endless stream of unpredictable keys (this is what > we need from urandom), but > > (2) we _can_ figure out how to use a single key to safely encrypt many > messages (this is what we need from SSL, PGP, etc.). > > For a cryptographer this doesn't even pass the laugh test. So that shouldn't be too concerning. > * What should the default CSPRNG be? There are good arguments for using a > cryptographically secure device random. (In my proposed implementation, for > device random, I use Security.framework on Apple platforms (because > /dev/urandom is not guaranteed to be available due to the sandbox, IIUC). On > Linux platforms, I would prefer to use getrandom() and avoid using file > system APIs, but getrandom() is new and unsupported on some versions of > Ubuntu that Swift supports. This is an issue in and of itself.) Now, a number > of these facilities strictly limit or do not guarantee availability of more > than a small number of random bytes at a time; they are recommended for > seeding other PRNGs but *not* as a routine source of random numbers. > Therefore, although device random should be available to users, it probably > shouldn’t be the default for the Swift standard library as it could have > negative consequences for the system as a whole. There follows the > significant task of implementing a CSPRNG correctly and securely for the > default PRNG. Theo give a talk a few years ago <https://www.youtube.com/watch?v=aWmLWx8ut20> on randomness and how these problems are approached in LibreSSL. Félix
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution