5

我正在尝试使用 UUID 生成随机数以用于 Twitter 反向身份验证。但显然 UUID 不是一个好的选择。那么,如何在每次剥离所有非单词字符时生成一个唯一的随机字符串,并注意它在使用后从内存中释放。以下代码崩溃。

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

    println("createdNonce:\(nonce)")

编辑: 我在 xcode6 beta2 上,我无法调试,xocde 崩溃,任何机会。好吧,CFRelease 部分对我来说是崩溃的。一旦我删除,它似乎工作正常,但我不知道这是否会造成内存泄漏。

至于为什么 UUID 可能不是用于 nonce 的好选择,似乎是因为 UUID 不是由真正的随机位组成的,请在此处参考此讨论:https ://github.com/aws/aws-sdk-ios/issues /30

4

7 回答 7

9

生成随机数的更正确方法可能是使用加密 RNG 生成随机字节。iOS恰好有这样一个东西:

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

// s is now a NSData containing 32 random bytes

然后使用 API 建议的任何格式(可能是 Base64)转换为字符串,例如

let base64str = s.base64EncodedStringWithOptions(0)

编辑:上面的方法似乎是 Twitter 在文档中使用的方法。见这里。我不能说 UUIDS 是否更容易预测。这取决于它们的生成方法。不过,SecRandomCopyBytes 似乎用于加密目的,因此使用起来应该是安全的。

于 2014-07-18T20:00:45.110 回答
3

Firebase 的 Authenticating Using Apple 教程提供的一个示例:

// 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
}
于 2020-05-05T23:17:38.080 回答
2

您的代码正在崩溃,因为您正在调用CFRelease.Inswift没有必要调用CFRelease.From swift guide

从带注释的 API 返回的 Core Foundation 对象在 Swift 中自动进行内存管理——您不需要自己调用 CFRetain、CFRelease 或 CFAutorelease 函数。

    var uuid: CFUUIDRef = CFUUIDCreate(nil)
    var nonce: CFStringRef = CFUUIDCreateString(nil, uuid)
   //Remove this swift will manage the memory managment.This line is causing crash  
   //CFRelease(uuid) 
    println("createdNonce:\(nonce)")

这段代码可以正常工作。不,这不会造成内存泄漏 swift 会管理它

于 2014-07-18T18:59:08.247 回答
2

使用 SwiftUI 5.x 和 CryptoKit,很容易:

import CryptoKit

let nonce = ChaChaPoly.Nonce.init()

正在使用:

let encryptedContent = try! ChaChaPoly.seal(inputBuffer, using: symmetricKey, nonce: ChaChaPoly.Nonce.init()).combined
于 2020-04-04T08:46:33.563 回答
1

这是一个适用于 Swift 4 的答案:

func generateNonce(lenght: Int) throws -> Data {
    let nonce = NSMutableData(length: lenght)
    let result = SecRandomCopyBytes(kSecRandomDefault, nonce!.length, nonce!.mutableBytes)
    if result == errSecSuccess {
        return nonce! as Data
    } else {
        throw Error
    }
}
于 2018-03-20T17:23:16.883 回答
0

这是一种更简单的方法:

    var temp = NSUUID.UUID().UUIDString
    var nonce = temp.stringByReplacingOccurrencesOfString("-", withString: "")
    println("createdNonce:\(nonce)")
于 2014-07-18T19:45:59.073 回答
0

这可能不是一个完美的解决方案,但想提出建议,因为这将花费你大量的 Twitter 反向身份验证。

尝试使用 cocoapod TWReverseAuth

于 2014-07-18T18:49:34.223 回答