{{ message }}

Instantly share code, notes, and snippets.

# Dean151/CryptoKitLottery.swift

Last active Jun 25, 2019
Generate Lottery Numbers using CryptoKit
 // Written by Thomas Durand (c)2019 ; all right reserved // See https://www.thomasdurand.fr/swift/cryptokit/2019/06/25/generating-lottery-numbers-with-cryptokit.html for more context /// Represent one `k among n` operation struct Draw { /// The number of number to draw (ie k) let draw: UInt /// The range of numbers to draw within (ie n) let among: ClosedRange /// Generate `draw` numbers within `among` func random() -> Set { var drawable = Set(among), drawnNumbers = Set() var generator = CryptoKitRandomNumberGenerator() while drawnNumbers.count < draw { guard let drawn = drawable.randomElement(using: &generator) else { break } drawable.remove(drawn) drawnNumbers.insert(drawn) } return drawnNumbers } } struct Lottery { /// The draws for that lottery /// Example draw 5 numbers within 1 and 49 & 1 number within 1 and 10. let draws: [Draw] /// Generate a lottery draw randomly func random() -> [Set] { return draws.map { \$0.random() } } } extension Lottery { static let frenchLoto = Lottery(draws: [ Draw(draw: 5, among: 1...49), Draw(draw: 1, among: 1...10) ]) static let euromillion = Lottery(draws: [ Draw(draw: 5, among: 1...50), Draw(draw: 2, among: 1...12) ]) } import CryptoKit /// RandomNumberGenerator using CryptoKit struct CryptoKitRandomNumberGenerator: RandomNumberGenerator { mutating func next() -> T where T : FixedWidthInteger, T : UnsignedInteger { // Let generate a symmetric key using CryptoKit. It'll be generated using best cryptographic practices to have strong randomness. // T will be 8 bytes at most (For UInt64) so generating a bits128 key (ie 16 bytes) is more than overkill already let key = SymmetricKey(size: .bits128) // Then we use the generated key to extract a random Unsigned Fixed Width Integer. return key.withUnsafeBytes { (pointer) -> T in // We have a pointer on random bytes generated by our class // Let convert those bytes to T ; in order to get our number. return pointer.bindMemory(to: T.self).baseAddress!.pointee } } } print(Lottery.frenchLoto.random()) print(Lottery.euromillion.random())