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 的加密安全替代方案?的主要内容,如果未能解决你的问题,请参考以下文章

iOS -雪花动画

带有计时器的 arc4random() 后应用程序崩溃? [复制]

gcd和nsthread的区别

这是不是可以将替代图标应用于 iOS 应用程序?

Python3 上是不是有 Ansible 的替代品

在表行上是不是有“keep-together='always'”的替代方法?