Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Random unique string generation to use as nonce (oauth)

Tags:

ios

swift

nonce

I am trying to use the UUID to generate as a nonce to be use for Twitter reverse authentication. But apparently the UUID is not a good choice. So how can I generate a unique random string every time stripping out all non-word characters, taking care that it gets release from memory after use. The following code crashes.

    var uuid: CFUUIDRef = CFUUIDCreate(nil)
    var nonce: CFStringRef = CFUUIDCreateString(nil, uuid)
    CFRelease(uuid)

    println("createdNonce:\(nonce)")

EDIT: I am on xcode6 beta2, and i can't debug, and xocde crashes, any chance it gets. So well, the CFRelease part is crashing for me. Once I remove, it seems to work fine, but I dont know if this will create a memory leak.

As to why UUID's might not be a good choice to use for nonce it seems is because, UUID's are not made of true random bits, referring this discussion here: https://github.com/aws/aws-sdk-ios/issues/30

like image 278
srinivas Avatar asked Jul 18 '14 18:07

srinivas


2 Answers

One example that's provided by Firebase's Authenticating Using Apple tutorial:

// Adapted from https://auth0.com/docs/api-auth/tutorials/nonce#generate-a-cryptographically-random-nonce
private func randomNonceString(length: Int = 32) -> String {
  precondition(length > 0)
  let charset: Array<Character> =
      Array("0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._")
  var result = ""
  var remainingLength = length

  while remainingLength > 0 {
    let randoms: [UInt8] = (0 ..< 16).map { _ in
      var random: UInt8 = 0
      let errorCode = SecRandomCopyBytes(kSecRandomDefault, 1, &random)
      if errorCode != errSecSuccess {
        fatalError("Unable to generate nonce. SecRandomCopyBytes failed with OSStatus \(errorCode)")
      }
      return random
    }

    randoms.forEach { random in
      if remainingLength == 0 {
        return
      }

      if random < charset.count {
        result.append(charset[Int(random)])
        remainingLength -= 1
      }
    }
  }

  return result
}
like image 26
Zorayr Avatar answered Oct 10 '22 14:10

Zorayr


A more correct way of generation a nonce would probably be to generate random bytes using a cryptographic RNG. iOS just happens to have such a thing:

var s = NSMutableData(length: 32)
SecRandomCopyBytes(kSecRandomDefault, UInt(s.length), UnsafePointer<UInt8>(s.mutableBytes))

// s is now a NSData containing 32 random bytes

Then convert to a string using whatever format the API suggests (probably Base64), e.g.

let base64str = s.base64EncodedStringWithOptions(0)

EDIT: The approach above seems to be the one Twitter uses in the docs. See here. I can't say if UUIDS are more easily predicted. It depends on the method they are generated. SecRandomCopyBytes seems to be used for cryptographic purposes though, so it should be safe to use.

like image 114
Krumelur Avatar answered Oct 10 '22 15:10

Krumelur