A massive +1 for this approach too. As a “least competent engineer” when it comes to random numbers, I’d really appreciate having safeguards in place to keep me from inadvertently shooting myself in the foot.
Dave > On Oct 11, 2017, at 11:21 AM, Cory Benfield via swift-evolution > <swift-evolution@swift.org> wrote: > > I strongly recommend building the padded room. > > Average to good engineers (which I assume is intended to be a proxy for > “engineers who know about CSPRNGs and have considered their personal threat > model”) know enough to work out what kind of RNG they have available and to > use the one most appropriate to their use-case. That means if the default is > “slow and cryptographically-secure” but they need “fast and not > cryptographically-secure", they’ll know enough to opt-out. If the default is > “fast and not cryptographically-secure”, they’ll also know enough not to > opt-out. In all cases the cost to this engineer of using the default is 20 > minutes (the time required to find out what the default is), and the cost of > using not-the-default is 20 minutes and a few lines of code. Marginal. > > The hypothetical least competent engineer, by definition, does not know > enough to check what RNG they have available. If the default is “slow”, > they’ll get “slow”: in the worst case, their code will be slower than it > needs to be because they could have used “fast” instead. If the default is > “fast”, they’ll get “fast”: in the worst case, their code will be vulnerable > to attack. This user will never swap away from the default, so the question > is which failure mode is preferable. I’d say it seems pretty obvious that “my > program is slow” is a better failure mode than “my program is vulnerable to > data exfiltration”. > > It’s completely worth it, IMO, to cost engineers that know what they’re doing > with an RNG a small amount of time to save us from the errors made by > engineers who don’t know. But it’s a false dichotomy to say that not having a > padded room is only a danger to the engineer writing the program: as Equifax > has demonstrated, we’re all on the hook for their work. > >> On 11 Oct 2017, at 10:02, Kevin Nattinger via swift-evolution >> <swift-evolution@swift.org> wrote: >> >> IMO, if we have the extensions on Int(eger)/Float(ingPoint)/Array >> (RandomAccessSequence?), they should just be for convenience and with a sane >> default RNG*, and users that need more should just use methods on the RNGs >> directly. >> >> *: I don't think the default necessarily needs to be a CSRNG; if there's a >> fast one, fine. Are we building a padded room for the least competent >> engineer or a tool for the average to good engineer to use efficiently? >> >>> On Oct 11, 2017, at 9:08 AM, Jeremy Pereira via swift-evolution >>> <swift-evolution@swift.org> wrote: >>> >>> I’m a bit late to the party on this one, but has anybody considered the >>> fact that you need a way for the user of the interface to override the >>> default random number source? >>> >>> For example, some applications require a cryptographically secure source, >>> others might eschew perfect entropy for speed. Still others might want >>> repeatability e.g. Minecraft lets you enter a seed when it does the World >>> generation so you can go back and play the same World again and again. For >>> unit testing, you might want to replace the random number generator with a >>> sequence of hard coded values so you can exactly control the code path that >>> the test takes. >>> >>> So if you have a protocol that describes an API for generating random >>> numbers called RNG, the extension on Int would look something like >>> >>> extension Int { >>> init(randomInRange: Countable{Closed}Range<Int>, rng: RNG = /* a CS random >>> number generator */) >>> } >>> >>>> On 7 Oct 2017, at 04:24, Chris Lattner via swift-evolution >>>> <swift-evolution@swift.org> wrote: >>>> >>>> >>>>> On Oct 5, 2017, at 10:58 AM, Nate Cook via swift-evolution >>>>> <swift-evolution@swift.org> wrote: >>>>> >>>>> The edge case is really the same (empty ranges), it’s about what we do >>>>> with the edge case. If we include the methods on integer types, usage >>>>> will look like this: >>>>> >>>>> let x = Int.random(in: 0..<5) // 3 >>>>> let y = Int.random(in: 0..<0) // runtime error >>>>> >>>>> If we only have the collection methods, usage will look like this: >>>>> >>>>> let x = (0..<5).random()! // 3 >>>>> let y = (0..<0).random()! // runtime error >>>> >>>> These aren’t the forms I was suggesting, what I meant was: >>>> >>>> extension Int { >>>> init(randomInRange: Countable{Closed}Range<Int>) >>>> } >>>> >>>> which gives: >>>> let x = Int(randomInRange: 0..<5) >>>> >>>> The point of this is that you’re producing an Int (or whatever type). >>>> Regardless of whether the initializer is failable or not, this is the >>>> preferred way of creating a new value with some property: it is an >>>> initializer with a label. >>>> >>>> -Chris >>>> >>>> >>>> _______________________________________________ >>>> swift-evolution mailing list >>>> swift-evolution@swift.org >>>> https://lists.swift.org/mailman/listinfo/swift-evolution >>> >>> _______________________________________________ >>> swift-evolution mailing list >>> swift-evolution@swift.org >>> https://lists.swift.org/mailman/listinfo/swift-evolution >> >> _______________________________________________ >> swift-evolution mailing list >> swift-evolution@swift.org >> https://lists.swift.org/mailman/listinfo/swift-evolution > > _______________________________________________ > swift-evolution mailing list > swift-evolution@swift.org > https://lists.swift.org/mailman/listinfo/swift-evolution _______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution