iOS 上是不是有替代 arc4random 的加密安全替代方案?
Posted
技术标签:
【中文标题】iOS 上是不是有替代 arc4random 的加密安全替代方案?【英文标题】:Is there a cryptographically secure alternative to arc4random on iOS?iOS 上是否有替代 arc4random 的加密安全替代方案? 【发布时间】:2017-06-25 23:32:59 【问题描述】:我想使用像 arc4random_uniform()
这样的 PRNG;但是,Wikipedia seems to think that rc4 is insecure。我没有足够的资金来确认自己,但安全性是我的用例的要求。
【问题讨论】:
完全没有 ios 和 co. 的经验,this function 似乎是官方的方式(基于 CTR-DRBG?),如果你真的要求 CPRNG(arc4 在技术上是一个流-cipher,但您似乎只需要 CPRNG 功能)。那么这个函数有什么问题呢? @sascha:我确实粗略地看了一下(我很快就会更新这个问题)。SecRandomCopyBytes()
旨在“生成加密安全随机字节数组”。我需要的是生成低于给定阈值的随机数;但公平地说,我仍在寻找通过SecRandomCopyBytes
成功完成此任务的人的例子。
那么你应该掌握一些基础知识。 [0,1) 中的均匀采样也以 32 或 64 个随机位 = 4 或 8 个随机字节开始。
@sascha:听起来你是说我应该自己推出解决方案?很公平。你介意给我指出正确的方向吗?我真的希望避免为此上一堂关于加密的课程。
这与加密无关。你已经得到了加密部分!获取随机字节是许多算法的核心。唯一留给您的是经典随机抽样(有一些算法怪癖,如 fp-math 和 co)。您没有指定要采样的内容,可能是 uniform [0,1),也可能是 uniform_int (0, 10000)。这些是经典示例,并且有很多资源(并且它们与加密相关的不多;从安全的随机字节开始,并且没有做一些非常错误的事情来产生偏见,一切都很好;如果您的任务本身定义明确)
【参考方案1】:
arc4random_uniform
被记录为“加密伪随机数生成器”,因此它应该可以用于此目的。不要将 RC4 的安全问题与arc4random
混淆。有关详细信息,请参阅Zaph's answer。 (我之前对此进行过研究,我记得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
这适用于任何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
上构建它,因为Integer
上没有.max
属性。
在 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
【讨论】:
我想这就是我要找的;但可以肯定的是,您介意链接到Integer
手册页吗?我在任何地方都找不到它。
Beta 版发布时,Apple 删除了所有 Swift 3.1 页面。你必须回顾一下像 swiftdoc(或者在我的情况下是 Dash)这样的档案:swiftdoc.org/v3.1/protocol/Integer以上是关于iOS 上是不是有替代 arc4random 的加密安全替代方案?的主要内容,如果未能解决你的问题,请参考以下文章