2

I'm using SecRandomCopyBytes for generate a secure random number.

Is there a way to specify a "range"?

I need to obtain the same behaviour of this Java piece of code:

SecureRandom r = new SecureRandom();
char x = (char)(r.nextInt(26) + 'a');

Any tips will appreciate!

UPDATE

Seeing that I made a silly question I feel compelled to share the solution, made extending Int type:

public extension Int {
  /**
  Create a random num Int in range
  :param: lower number Int
  :param: upper number Int
  :return: random number Int
  */
  public static func random(#min: Int, max: Int) -> Int {
     return Int(arc4random_uniform(UInt32(max - min + 1))) + min
  }

  /**
  Create a secure random num Int in range
  :param: lower number Int
  :param: upper number Int
  :return: random number Int
  */
  public static func secureRandom(#min: Int, max: Int) -> Int {
    if max == 0 {
        NSException(name: "secureRandom", reason: "max number must be > 0", userInfo: nil).raise()
    }
    var randomBytes = UnsafeMutablePointer<UInt8>.alloc(8)
    SecRandomCopyBytes(kSecRandomDefault, 8, randomBytes)
    let randomNumber = unsafeBitCast(randomBytes, UInt.self)
    return Int(randomNumber) % max + min
  }
}
Luca Davanzo
  • 21,000
  • 15
  • 120
  • 146
  • This solution doesn't return random number between min..max but in the range min..(min+max) I would rather suggest using Swift's 4.2 implementation: https://stackoverflow.com/a/39768472/1245231 – petrsyn Dec 20 '18 at 17:28

2 Answers2

2

Edit: Swift 4.2 allows to generate random numbers using Int class:

let randomNumber = Int.random(in: 0 ..< 26)

The random source should be cryptographically secure SystemRandomNumberGenerator

See also:

Old answer: iOS 9 introduced GameplayKit which provides SecureRandom.nextInt() Java equivalent.

To use it in Swift 3:

import GameplayKit

// get random Int
let randomInt = GKRandomSource.sharedRandom().nextInt(upperBound: 26)

See this answer for more info: https://stackoverflow.com/a/31215189/1245231

petrsyn
  • 5,054
  • 3
  • 45
  • 48
0

You can always specify a range by applying modulo and addition, check this pseudocode:

// random number in the range 1985-2014 
r = rand() % 30 + 1985
nburk
  • 22,409
  • 18
  • 87
  • 132
  • 1
    Oh.. I just realized I made the stupidest question in the story! – Luca Davanzo Jun 11 '15 at 14:43
  • haha no worries :D sometimes the instinct let's you post a question before thinking it through ;) – nburk Jun 11 '15 at 14:46
  • This also happens after hours of code-porting! Kill me! – Luca Davanzo Jun 11 '15 at 14:51
  • 1
    This solution will result in a biased random number generator unless your max argument happens to be divisible by UInt8.max. This problem is commonly referred to as modulo bias. See this post for a great explanation, and a more secure solution: http://stackoverflow.com/a/10984975 – Lockyer Aug 20 '16 at 00:52