Using Secrandomcopybytes in Swift

Using SecRandomCopyBytes in Swift

You were close, but return inside the closure returns
from the closure, not from the outer function.
Therefore only SecRandomCopyBytes() should be called in the
closure, and the result passed back.

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
}
}

For a "single-expression closure" the closure type can inferred
automatically, so this can be shortened to

func generateRandomBytes() -> String? {

var keyData = Data(count: 32)
let result = keyData.withUnsafeMutableBytes {
SecRandomCopyBytes(kSecRandomDefault, 32, $0)
}
if result == errSecSuccess {
return keyData.base64EncodedString()
} else {
print("Problem generating random bytes")
return nil
}
}

Swift 5 update:

func generateRandomBytes() -> String? {

var keyData = Data(count: 32)
let result = keyData.withUnsafeMutableBytes {
SecRandomCopyBytes(kSecRandomDefault, 32, $0.baseAddress!)
}
if result == errSecSuccess {
return keyData.base64EncodedString()
} else {
print("Problem generating random bytes")
return nil
}
}

Swift language: How to call SecRandomCopyBytes

This appears to work:

let data = NSMutableData(length: Int(length))
let result = SecRandomCopyBytes(kSecRandomDefault, length, UnsafeMutablePointer<UInt8>(data.mutableBytes))

How do I generate a cryptographically secure random number to use for bearer tokens?

For Vapor you can generate a token like so:

[UInt8].random(count: 32).base64

That will be cryptographically secure to use. You can use it like in this repo

Random 256bit key using SecRandomCopyBytes( ) in iOS

The result of SecRandomCopyBytes should always be 0, unless there is some error (which I can't imagine why that might happen) and then the result would be -1. You're not going to convert that into a NSString.

The thing you're trying to get are the random bytes which are being written into the mutable bytes section, and that's what you'll be using as your "master key" instead of the UUID string.

The way I would do it would be:

uint8_t randomBytes[16];
int result = SecRandomCopyBytes(kSecRandomDefault, 16, randomBytes);
if(result == 0) {
NSMutableString *uuidStringReplacement = [[NSMutableString alloc] initWithCapacity:16*2];
for(NSInteger index = 0; index < 16; index++)
{
[uuidStringReplacement appendFormat: @"%02x", randomBytes[index]];
}
NSLog(@"uuidStringReplacement is %@", uuidStringReplacement);
} else {
NSLog(@"SecRandomCopyBytes failed for some reason");
}

Using a UUIDString feels secure enough to me, but it sounds like your third party security audit firm is trying really hard to justify their fees.

EDITED: since I'm now starting to collect downvotes because of Vlad's alternative answer and I can't delete mine (as it still has the accepted checkmark), here's another version of my code. I'm doing it with 16 random bytes (which gets doubled in converting to Hex).

How do you use Data.withUnsafeMutbleBytes in Swift 3?

Ignoring the SecRandomCopyBytes part, the overall full syntax is:

var key = Data(count: 64)
key.withUnsafeMutableBytes { (ptr:UnsafeMutablePointer<UInt8>) -> Void in
print("here")
}

Putting SecRandomCopyBytes doesn't seem to make any serious difference:

var key = Data(count: 64)
key.withUnsafeMutableBytes { (ptr:UnsafeMutablePointer<UInt8>) -> Void in
SecRandomCopyBytes(kSecRandomDefault, 64, ptr)
print("here")
}

That might not be your final code, of course, but the point is that it compiles and permits you to proceed to develop the code further. — Actually, just for laughs, I tried the following, to see whether we really were populating the Data with random bytes, and it seems to be working fine:

    var key = Data(count: 64)
key.withUnsafeMutableBytes { (ptr:UnsafeMutablePointer<UInt8>) -> Void in
_ = SecRandomCopyBytes(kSecRandomDefault, 64, ptr)
}
for b in key {print(b)}

Note the use of _ = to suppress the warning about the unused result.

Generate random number in range with SecRandomCopyBytes

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


Related Topics



Leave a reply



Submit