2017-06-25 3 views
1

arc4random_uniform()のようなPRNGを使用したいと思います。しかし、Wikipedia seems to think that rc4 is insecure。私は自分自身を確認するための資金を持っていませんが、セキュリティは私のユースケースの要件です。iOS上のarc4randomの代わりに暗号的に安全な方法はありますか?

+0

iOSと共同で、まったく経験のない、[この機能](https://で開発あなたが本当にCPRNGを求めているのであれば(arc4は技術的にはストリーム暗号ですが、CPRNGのみを望んでいるようです)能力)。では、この関数の何が問題になっていますか? – sascha

+0

@サシャ:私はそれを簡潔に見ていました(私はまもなく質問を更新します)。 ['SecRandomCopyBytes()'](https://developer.apple.com/documentation/security/1399291-secrandomcopybytes)は、「暗号的に安全なランダムバイトの配列を生成する」ように設計されています。私が必要とするのは、与えられた閾値以下の乱数を生成することです。しかし、公正であるために、私は 'SecRandomCopyBytes'でこれを成功裏に達成した人々の例を探しています。 –

+0

次に、いくつかの基本を取り上げる必要があります。 [0,1]での一様サンプリングは、32または64ランダムビット= 4または8ランダムバイトからも開始されます。 – sascha

答えて

4

arc4random_uniformは、「暗号擬似乱数ジェネレータ」として文書化されているため、この目的には問題ありません。 RC4のセキュリティ上の問題をarc4randomと混同しないでください。詳細はZaph's answerを参照してください。 (私は以前これを研究していましたが、arc4randomは他のアプローチと同じくらい安全ですが、私は自分の記憶を信頼する以上にザフを信頼しています)。

あなたが緊張していたら、使用は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だから、ちょうどそれを見ることができます。 Integerには.maxプロパティがありませんので、我々はIntegerでこれを構築することはできません

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 
    } 
} 

:スウィフトで同じアプローチを適用するように見えます。スウィフト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 
    } 
} 
+0

これは私が探しているものだと思います。確かに、 'Integer'のマニュアルページにリンクしてもいいですか?私はどこでもそれを見つけることができません。 –

+1

アップルは、ベータ版が出たときにすべてのSwift 3.1ページを削除しました。あなたswiftdoc(または私の場合は、ダッシュ)のようなアーカイブを振り返らなければならない:http://swiftdoc.org/v3.1/protocol/Integer/ –

関連する問題