我想使用像 arc4random_uniform()
这样的PRNG;但是,Wikipedia seems to think that rc4 is insecure。我没有足够的钱来确认自己,但是安全是我用例的要求。
最佳答案
arc4random_uniform
被记录为“加密伪随机数生成器”,因此可以满足此目的。不要将RC4的安全性问题与arc4random
混淆。有关更多详细信息,请参见Zaph's answer。 (我之前对此进行了研究,我记得arc4random
与其他方法一样安全,但是我对Zaph的信任比对我自己的内存的信任还要多。)
就是说,如果您很紧张,则要使用的工具是SecRandomCopyBytes
(或者,您可以从/dev/random
读取,这正是SecRandomCopyBytes
的功能)。
从SecRandomCopyBytes
获取随机值比它应该的难,但也不太难。这是您以一种非常通用的方式进行操作的方法(快速3):
extension Integer {
static func makeRandom() -> Self {
var result: Self = 0
withUnsafeMutablePointer(to: &result) { resultPtr in
resultPtr.withMemoryRebound(to: UInt8.self, capacity: MemoryLayout<Self>.size) { bytePtr in
SecRandomCopyBytes(nil, MemoryLayout<Self>.size, bytePtr)
}
}
return result
}
}
这适用于任何
Integer
。基本上,我们将一堆随机字节解释为Integer
。 (顺便说一句,这种方法在浮点值上效果不佳。可以做到这一点,但是您会发现并非所有位模式实际上都是浮点中的“数字”。因此稍微复杂一些。)现在,您希望在不引入偏差的情况下获得这些值。只是说
x % limit
会创建modulo bias。不要那样做正确的方法是执行arc4random_uniform
要做的事情。它是open source,所以您可以看看它。在Swift中应用相同的方法如下所示:extension Int {
static func makeRandom(betweenZeroAnd limit: Int) -> Int {
assert(limit > 0)
// Convert our range from [0, Int.max) to [Int.max % limit, Int.max)
// This way, when we later % limit, there will be no bias
let minValue = Int.max % limit
var value = 0
// Keep guessing until we're in the range.
// In theory this could loop forever. It won't. A couple of times at worst
// (mostly because we'll pick some negatives that we'll throw away)
repeat {
value = makeRandom()
} while value < minValue
return value % limit
}
}
我们无法在
Integer
上构建它,因为.max
上没有Integer
属性。在Swift 4中,所有这些都用
FixedWidthInteger
清理了,我们可以使它更通用:extension FixedWidthInteger {
static func makeRandom() -> Self {
var result: Self = 0
withUnsafeMutablePointer(to: &result) { resultPtr in
resultPtr.withMemoryRebound(to: UInt8.self, capacity: MemoryLayout<Self>.size) { bytePtr in
SecRandomCopyBytes(nil, MemoryLayout<Self>.size, bytePtr)
}
}
return result
}
static func makeRandom(betweenZeroAnd limit: Self) -> Self {
assert(limit > 0)
// Convert our range from [0, Int.max) to [Int.max % limit, Int.max)
// This way, when we later % limit, there will be no bias
let minValue = Self.max % limit
var value: Self = 0
// Keep guessing until we're in the range.
// In theory this could loop forever. It won't. A couple of times at worst
// (mostly because we'll pick some negatives that we'll throw away)
repeat {
value = makeRandom()
} while value < minValue
return value % limit
}
}
关于ios - iOS上是否有加密安全的替代arc4random的替代方案?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44751523/