# Generating lottery numbers using CryptoKit

Why? Because we can!

WWDC19 announcements came with CryptoKit; a new framework designed for making cryptography easy.

Today, I want to show how to use CryptoKit to generate numbers.

It’ll a better generator than `arc4random` used by default on iOS since it generate cryptographic keys, keys that are supposed to be the most random and entropic possible!

## A model to generate lottery numbers

First, what are lottery draws?

It’s one or more k among n draws!

``````/// 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<Int>

/// Generate `draw` numbers within `among`
func random() -> Set<Int> {
// TODO!
return []
}
}``````

We can then define a lottery as an array of Draws:

``````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<Int>] {
return draws.map { \$0.random() }
}
}``````

The most popular french lotteries can then be defined easily within the application:

``````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)
])
}``````

Once the `Draw.random()` method gets implemented, we will be able to generate lottery numbers very easily:

``````// Output for now: [Set([]), Set([])]
print(Lottery.euromillion.random())``````

## Randomness using default implementation

Generating k number among a range is quite straightforward:

``````/// Generate `draw` numbers within `among`
func random() -> Set<Int> {
var drawable = Set(among), drawnNumbers = Set<Int>()
while drawnNumbers.count < draw {
guard let drawn = drawable.randomElement() else {
// If somehow we do not find any element, it means we want to draw more elements than available
// Let just break the loop and return all elements.
break
}
// Mark the number as already drawn
drawable.remove(drawn)
// And add the number to the draw
drawnNumbers.insert(drawn)
}
return drawnNumbers
}``````

In this example, the random is handled by `randomElement()`.

That uses by default the `SystemRandomNumberGenerator` that will be either:

• `arc4random_buf` on Apple platforms
• `getrandom` if available or `/dev/urandom` on unix platforms.

## Using CryptoSwift’s randomness

Okay, here it becomes a little hacky; why not using the random bytes securely generated for a key as random source for the lottery numbers?

Doing so is quite easy, since we can use `randomElement(using generator: inout RandomNumberGenerator)`

``````import CryptoKit

/// RandomNumberGenerator using CryptoKit
struct CryptoKitRandomNumberGenerator: RandomNumberGenerator {
mutating func next<T>() -> 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.
}
}
}``````

And now we can pick numbers using our new generator:

``````var generator = CryptoKitRandomNumberGenerator()
let drawn = drawable.randomElement(using: &generator)``````

And, in our previous `Draw.random()` implementation, it’ll give us this:

``````/// Generate `draw` numbers within `among`
func random() -> Set<Int> {
var drawable = Set(among), drawnNumbers = Set<Int>()
var generator = CryptoKitRandomNumberGenerator()
while drawnNumbers.count < draw {
guard let drawn = drawable.randomElement(using: &generator) else {
break
}
drawable.remove(drawn)
drawnNumbers.insert(drawn)
}
return drawnNumbers
}``````

And this is it, you can now generate draws for all sort of Lotteries you may define using this snippet of code

``````// Output: [Set([27, 13, 21, 29, 4]), Set([1, 3])]
// If you win with those, I claim a 5% tax :D
print(Lottery.euromillion.random())``````

## What now?

Okay, let’s face it, I really think that using CryptoKit here is a bit overkill; but why not? It’s so easy to do!

CryptoKit make things like generating secure keys, encrypting, and many more cryptographic operation fairly easy! If you’re into cryptography, you should definitely give it a try in a Playground right away!

And if you have questions about CryptoKit: contact-me via GitHub or Twitter)

### Don’t miss a thing!

Don't miss any of my indie dev stories, app updates, or upcoming creations!
Stay in the loop and be the first to experience my apps, betas and stories of my indie journey.

Thank you for registering!
You’ll retrieve all of my latest news!