seeding arc4random() in iOS

2019-02-07 22:13发布

问题:

From what I can gather arc4random() generates much better random numbers than rand() does, however I haven't seen a way to seed it, and I would like to just like using srand(). Is there a way?

回答1:

That's not what arc4random is designed to do. As the documentation states:

The arc4random() function provides a high quality 32-bit pseudo-random number very quickly. arc4random() seeds itself on a regular basis from the kernel strong random number subsystem described in random(4).

Since it is re-seeds itself from an entropy source anyway, you gain nothing by seeding it manually, and in fact, such a method does not exist.



回答2:

You can actually do this in iOS 9.

import GameKit

let source = GKARC4RandomSource(seed: "hello world".data(using: .utf8)!)
source.dropValues(1024)
source.nextInt() // <-- your number

According to the docs:

Arc4 based random sources have repeatable initial sequences. If used for obfuscation you should drop N values from the start, where N should be any number larger than 768 to ensure the initial sequence is flushed.

So as long as you use the same seed data (obviously without using ! in production code) and the same number of dropped values, you'll get the same results.



回答3:

In Swift 3 I'm using srand48() and drand48() when I need a seeded value. I made this function that seems to work well enough for my needs:

func seeded_rand(seed:Int, min:Double, max:Double) -> Int
{
    srand48(seed)
    return Int(round(drand48() * (max-min)) + min)
}


回答4:

You can add a byte sequence as randomness to arc4random by using: arc4random_addrandom()

http://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man3/arc4random.3.html



回答5:

You don't actually need to seed it... it seeds itself on the first call. Check out the documentation by calling

man arc4random

in your shell. The relevant line, under DESCRIPTION, is:

There is no need to call arc4random_stir() before using arc4random(),
since arc4random() automatically initializes itself.