Noo*_*bot 1 security random ios
我想使用 PRNG 之类的arc4random_uniform();然而,维基百科似乎认为 rc4 是不安全的。我没有足够的资金来确认自己,但安全性是我的用例的要求。
arc4random_uniform被记录为“加密伪随机数生成器”,因此对于此目的应该没问题。不要将 RC4 的安全问题与arc4random. 有关更多详细信息,请参阅Zaph 的回答。(我之前研究过这个,我记得arc4random它和其他方法一样安全,但我相信 Zaph 胜过我相信我自己的记忆。)
也就是说,如果您感到紧张,您想要使用的工具是SecRandomCopyBytes(或者您可以从 读取/dev/random,这正是SecRandomCopyBytes规范所做的)。
从中获取随机值SecRandomCopyBytes比应有的更难,但也不算太难。以下是您以高度通用的方式(Swift 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
}
}
Run Code Online (Sandbox Code Playgroud)
这适用于任何Integer. 基本上我们将一堆随机字节解释为Integer. (顺便说一句,这种方法对于浮点值几乎不起作用。您可以这样做,但您会发现并非所有位模式实际上都是浮点数中的“数字”。所以它有点复杂。)
现在您希望在不引入偏差的情况下获得一个范围内的这些值。只是说x % limit会产生模偏差。不要那样做。正确的方法是做什么arc4random_uniform就做什么。它是开源的,所以你可以去看看它。在 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
}
}
Run Code Online (Sandbox Code Playgroud)
我们无法在此基础上进行构建,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
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1206 次 |
| 最近记录: |