在 Swift 中使用 SecRandomCopyBytes
Using SecRandomCopyBytes in Swift
我想在 Swift 3.0 中使用 SecRandomCopyBytes
生成随机字节。这是我在 Swift 2.2
中的做法
private static func generateRandomBytes() -> String? {
let data = NSMutableData(length: Int(32))
let result = SecRandomCopyBytes(kSecRandomDefault, 32, UnsafeMutablePointer<UInt8>(data!.mutableBytes))
if result == errSecSuccess {
return data!.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0))
} else {
print("Problem generating random bytes")
return nil
}
}
在 Swift 3 中,我尝试这样做,因为我知道现在 unsafemutablebytes 的概念不同了,但它不允许我这样做 return。如果我注释掉 return 部分,它仍然显示 Generic Parameter ResultType could not be inferred
fileprivate static func generateRandomBytes() -> String? {
var keyData = Data(count: 32)
_ = keyData.withUnsafeMutableBytes {mutableBytes in
let result = SecRandomCopyBytes(kSecRandomDefault, keyData.count, mutableBytes)
if result == errSecSuccess {
return keyData.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0))
} else {
print("Problem generating random bytes")
return nil
}
}
return nil
}
有人知道如何解决这个问题吗?
谢谢
你很接近,但是 return
在闭包内 returns
来自闭包,而不是来自外部函数。
因此只应调用 SecRandomCopyBytes()
关闭,返回结果。
func generateRandomBytes() -> String? {
var keyData = Data(count: 32)
let result = keyData.withUnsafeMutableBytes {
(mutableBytes: UnsafeMutablePointer<UInt8>) -> Int32 in
SecRandomCopyBytes(kSecRandomDefault, 32, mutableBytes)
}
if result == errSecSuccess {
return keyData.base64EncodedString()
} else {
print("Problem generating random bytes")
return nil
}
}
对于"single-expression closure"闭包类型可以推断
自动,因此可以缩短为
func generateRandomBytes() -> String? {
var keyData = Data(count: 32)
let result = keyData.withUnsafeMutableBytes {
SecRandomCopyBytes(kSecRandomDefault, 32, [=11=])
}
if result == errSecSuccess {
return keyData.base64EncodedString()
} else {
print("Problem generating random bytes")
return nil
}
}
Swift 5 更新:
func generateRandomBytes() -> String? {
var keyData = Data(count: 32)
let result = keyData.withUnsafeMutableBytes {
SecRandomCopyBytes(kSecRandomDefault, 32, [=12=].baseAddress!)
}
if result == errSecSuccess {
return keyData.base64EncodedString()
} else {
print("Problem generating random bytes")
return nil
}
}
根据 Apple Documentation 看起来类似于:
public func randomData(ofLength length: Int) throws -> Data {
var bytes = [UInt8](repeating: 0, count: length)
let status = SecRandomCopyBytes(kSecRandomDefault, length, &bytes)
if status == errSecSuccess {
return Data(bytes: bytes)
}
// throw an error
}
或作为额外的初始值设定项:
public extension Data {
public init(randomOfLength length: Int) throws {
var bytes = [UInt8](repeating: 0, count: length)
let status = SecRandomCopyBytes(kSecRandomDefault, length, &bytes)
if status == errSecSuccess {
self.init(bytes: bytes)
} else {
// throw an error
}
}
}
这是使用 Swift 5:
实现功能的最简单 "Swiftiest" 方法
func generateRandomBytes() -> String? {
var bytes = [UInt8](repeating: 0, count: 32)
let result = SecRandomCopyBytes(kSecRandomDefault, bytes.count, &bytes)
guard result == errSecSuccess else {
print("Problem generating random bytes")
return nil
}
return Data(bytes).base64EncodedString()
}
通常,在 Swift 中,当函数的控制流取决于表达式的成功或失败或是否存在非零值。
我想在 Swift 3.0 中使用 SecRandomCopyBytes
生成随机字节。这是我在 Swift 2.2
private static func generateRandomBytes() -> String? {
let data = NSMutableData(length: Int(32))
let result = SecRandomCopyBytes(kSecRandomDefault, 32, UnsafeMutablePointer<UInt8>(data!.mutableBytes))
if result == errSecSuccess {
return data!.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0))
} else {
print("Problem generating random bytes")
return nil
}
}
在 Swift 3 中,我尝试这样做,因为我知道现在 unsafemutablebytes 的概念不同了,但它不允许我这样做 return。如果我注释掉 return 部分,它仍然显示 Generic Parameter ResultType could not be inferred
fileprivate static func generateRandomBytes() -> String? {
var keyData = Data(count: 32)
_ = keyData.withUnsafeMutableBytes {mutableBytes in
let result = SecRandomCopyBytes(kSecRandomDefault, keyData.count, mutableBytes)
if result == errSecSuccess {
return keyData.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0))
} else {
print("Problem generating random bytes")
return nil
}
}
return nil
}
有人知道如何解决这个问题吗?
谢谢
你很接近,但是 return
在闭包内 returns
来自闭包,而不是来自外部函数。
因此只应调用 SecRandomCopyBytes()
关闭,返回结果。
func generateRandomBytes() -> String? {
var keyData = Data(count: 32)
let result = keyData.withUnsafeMutableBytes {
(mutableBytes: UnsafeMutablePointer<UInt8>) -> Int32 in
SecRandomCopyBytes(kSecRandomDefault, 32, mutableBytes)
}
if result == errSecSuccess {
return keyData.base64EncodedString()
} else {
print("Problem generating random bytes")
return nil
}
}
对于"single-expression closure"闭包类型可以推断 自动,因此可以缩短为
func generateRandomBytes() -> String? {
var keyData = Data(count: 32)
let result = keyData.withUnsafeMutableBytes {
SecRandomCopyBytes(kSecRandomDefault, 32, [=11=])
}
if result == errSecSuccess {
return keyData.base64EncodedString()
} else {
print("Problem generating random bytes")
return nil
}
}
Swift 5 更新:
func generateRandomBytes() -> String? {
var keyData = Data(count: 32)
let result = keyData.withUnsafeMutableBytes {
SecRandomCopyBytes(kSecRandomDefault, 32, [=12=].baseAddress!)
}
if result == errSecSuccess {
return keyData.base64EncodedString()
} else {
print("Problem generating random bytes")
return nil
}
}
根据 Apple Documentation 看起来类似于:
public func randomData(ofLength length: Int) throws -> Data {
var bytes = [UInt8](repeating: 0, count: length)
let status = SecRandomCopyBytes(kSecRandomDefault, length, &bytes)
if status == errSecSuccess {
return Data(bytes: bytes)
}
// throw an error
}
或作为额外的初始值设定项:
public extension Data {
public init(randomOfLength length: Int) throws {
var bytes = [UInt8](repeating: 0, count: length)
let status = SecRandomCopyBytes(kSecRandomDefault, length, &bytes)
if status == errSecSuccess {
self.init(bytes: bytes)
} else {
// throw an error
}
}
}
这是使用 Swift 5:
实现功能的最简单 "Swiftiest" 方法func generateRandomBytes() -> String? {
var bytes = [UInt8](repeating: 0, count: 32)
let result = SecRandomCopyBytes(kSecRandomDefault, bytes.count, &bytes)
guard result == errSecSuccess else {
print("Problem generating random bytes")
return nil
}
return Data(bytes).base64EncodedString()
}
通常,在 Swift 中,当函数的控制流取决于表达式的成功或失败或是否存在非零值。