> 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

Reply via email to