Swift language: How to call SecRandomCopyBytes - ios

From Objective-C, I could do this:
NSMutableData *data = [NSMutableData dataWithLength:length];
int result = SecRandomCopyBytes(kSecRandomDefault, length, data.mutableBytes);
When attempting this in Swift, I have the following:
let data = NSMutableData(length: Int(length))
let result = SecRandomCopyBytes(kSecRandomDefault, length, data.mutableBytes)
but I get this compiler error:
'Void' is not identical to 'UInt8'
The data.mutableBytes parameter is rejected because the types do not match, but I can't figure out how to coerce the parameter (and I'm presuming it's somehow safe to do).

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

Swift 5
let count: Int = <byteCount>
var data = Data(count: count)
let result = data.withUnsafeMutableBytes {
SecRandomCopyBytes(kSecRandomDefault, count, $0.baseAddress!)
}
Swift 4:
var data = Data(count: <count>)
let result = data.withUnsafeMutableBytes { mutableBytes in
SecRandomCopyBytes(kSecRandomDefault, data.count, mutableBytes)
}

Swift 4 version:
let count = 16
var data = Data(count: count)
_ = data.withUnsafeMutableBytes {
SecRandomCopyBytes(kSecRandomDefault, count, $0)
}

Related

How can I convert UIImage to Byte Array In Swift 4

I'm trying to convert an UIimage to byte array in swift . I've searched a lot but the solutions are either too old ( for swift 2 ) or they don't work .
Does anyone know a way to do so ?!
Thanks
Solution above is incorrect, extremely slow to copy byte per byte
It took 4 seconds for a big image, and 0.02s with the following (new constructor from Swift3)
let data: [UInt8] = [...]
let image = UIImage(data: Data(bytes: data, count: data.count))
guard let dataPng: Data = image.pngData() else { return [] }
let finalData = [UInt8](dataPng)
Try this!!
guard let image = UIImage(named: "someImage") else { return }
let data = UIImageJPEGRepresentation(image, 1.0)
OR you can convert UIImage to NSData
func getArrayOfBytesFromImage(imageData:NSData) -> NSMutableArray
{
// the number of elements:
let count = data.length / MemoryLayout<UInt8>.size
// create array of appropriate length:
var bytes = [UInt8](repeating: 0, count: count)
// copy bytes into array
imageData.getBytes(&bytes, length:count)
var byteArray:NSMutableArray = NSMutableArray()
for (var i = 0; i < count; i++) {
byteArray.addObject(NSNumber(unsignedChar: bytes[i]))
}
return byteArray
}

Swift 3 Compiler Error : 'bytes' is unavailable: use withUnsafeBytes instead

I have an encrypting method in Swift 2.2. How can I get bytes from data in Swift 3?
Here is my code:
func myEncrypt(encryptData:String) -> String? {
//security key must be 24charachters
let myKeyData : Data = "*******".data(using: String.Encoding.utf8)!
let myRawData : Data = encryptData.data(using: String.Encoding.utf8)!
let mykeydatamd5 = Data(bytes: myKeyData.bytes, count: 24)
let Crypto_status: CCCryptorStatus = CCCrypt(operation, algoritm, options, mykeydatamd5.bytes , keyLength, nil, myRawData.bytes, myRawData.count, buffer, buffer_size, &num_bytes_encrypted)
if UInt32(Crypto_status) == UInt32(kCCSuccess){
let myResult: Data = Data(bytes: buffer, count: num_bytes_encrypted)
free(buffer)
return myResult.base64EncodedString()
}else{
free(buffer)
return nil
}
}
The error occurs in myKeyData.bytes and myRawData.bytes.
As shown in the error message, you need to use withUnsafeBytes instead.
Generally, if you have some expression like this:
let result = someFunc(..., data.bytes, ...)
You need to rewrite it as:
let result = data.withUnsafeBytes {dataBytes in
someFunc(..., dataBytes, ...)
}
If you use multiple .bytes in a single expression, you may need to use nested withUnsafeBytes. In your case the related part of your code should be something like this:
let mykeydatamd5 = myKeyData.subdata(in: 0..<24) //Assuming myKeyData.count >= 24
let crypto_status: CCCryptorStatus = mykeydatamd5.withUnsafeBytes {mykeydataBytes in
myRawData.withUnsafeBytes {myRawDataBytes in
CCCrypt(operation, algoritm, options, mykeydataBytes, keyLength, nil, myRawDataBytes, myRawData.count, buffer, buffer_size, &num_bytes_encrypted)
}
}
Try this
func myEncrypt(encryptData:String) -> String? {
//security key must be 24charachters
var myKeyData = [UInt8]()
var myRawData = [UInt8]()
for char in "*******".utf8{
myKeyData += [char]
}
for char in encryptData.utf8{
myRawData += [char]
}
let mykeydatamd5 = Data(bytes: myKeyData, count: 24)
let Crypto_status: CCCryptorStatus = CCCrypt(operation, algoritm, options, mykeydatamd5.bytes , keyLength, nil, myRawData, myRawData.count, buffer, buffer_size, &num_bytes_encrypted)
if UInt32(Crypto_status) == UInt32(kCCSuccess){
let myResult: Data = Data(bytes: buffer, count: num_bytes_encrypted)
free(buffer)
return myResult.base64EncodedString()
}else{
free(buffer)
return nil
}
}
Hope it will help you

convert byte array to UIImage in Swift

I want to convert byte array to UIImage in my project.
For that I found something here.
After that I tried to convert that code in swift but failed.
Here is my swift version of the code.
func convierteImagen(cadenaImagen: NSMutableString) -> UIImage {
var strings: [AnyObject] = cadenaImagen.componentsSeparatedByString(",")
let c: UInt = UInt(strings.count)
var bytes = [UInt8]()
for (var i = 0; i < Int(c); i += 1) {
let str: String = strings[i] as! String
let byte: Int = Int(str)!
bytes.append(UInt8(byte))
// bytes[i] = UInt8(byte)
}
let datos: NSData = NSData(bytes: bytes as [UInt8], length: Int(c))
let image: UIImage = UIImage(data: datos)!
return image
}
but I'm getting error:
EXC_BAD_INSTRUCTION
which is displayed in screenshot as follow.
Please help to solve this problem.
If you are using the example data that you quoted, those values are NOT UInts - they are signed Ints. Passing a negative number into UInt8() does indeed seem to cause a runtime crash - I would have thought it should return an optional. The answer is to use the initialiser using the bitPattern: signature, as shown in the Playground example below:
let o = Int8("-127")
print(o.dynamicType) // Optional(<Int8>)
// It's optional, so we need to unwrap it...
if let x = o {
print(x) // -127, as expected
//let b = UInt8(x) // Run time crash
let b = UInt8(bitPattern: x) // 129, as it should be
}
Therefore your function should be
func convierteImagen(cadenaImagen: String) -> UIImage? {
var strings = cadenaImagen.componentsSeparatedByString(",")
var bytes = [UInt8]()
for i in 0..< strings.count {
if let signedByte = Int8(strings[i]) {
bytes.append(UInt8(bitPattern: signedByte))
} else {
// Do something with this error condition
}
}
let datos: NSData = NSData(bytes: bytes, length: bytes.count)
return UIImage(data: datos) // Note it's optional. Don't force unwrap!!!
}

Convert UIImage to byte array in swift

How can I convert a UIimage into a Byte Array, so I can upload it into my web service?
You can actually use a couple of lines to do it
guard let image = UIImage(named: "someImage"),
let data = image.jpegData(compressionQuality: 1.0) else { return }
// OR
guard let image = UIImage(named: "someImage"),
let data = image.pngData() else { return }
The number should range from 0.0 to 1.0 and sets the jpeg quality. PNG is lossless so there is no need for compression quality identifier but be aware that the file size can be about 10 times higher
--- update ---
Updated for Swift 5.1
You can convert UIImage to NSData and pass it to this method
func getArrayOfBytesFromImage(imageData:NSData) -> NSMutableArray
{
// the number of elements:
let count = imageData.length / sizeof(UInt8)
// create array of appropriate length:
var bytes = [UInt8](count: count, repeatedValue: 0)
// copy bytes into array
imageData.getBytes(&bytes, length:count * sizeof(UInt8))
var byteArray:NSMutableArray = NSMutableArray()
for (var i = 0; i < count; i++) {
byteArray.addObject(NSNumber(unsignedChar: bytes[i]))
}
return byteArray
}
Swift 5, iOS 14 version based on toofani answer, minimal changes
func getArrayOfBytesFromImage(imageData:NSData) -> Array<UInt8>
{
// the number of elements:
let count = imageData.length / MemoryLayout<Int8>.size
// create array of appropriate length:
var bytes = [UInt8](repeating: 0, count: count)
// copy bytes into array
imageData.getBytes(&bytes, length:count * MemoryLayout<Int8>.size)
var byteArray:Array = Array<UInt8>()
for i in 0 ..< count {
byteArray.append(bytes[i])
}
return byteArray
}
So a complete sequence looks like this... assuming I got a UIImage I extract the data and then recombine it.
let data = imageX.pngData()
bytes = getArrayOfBytesFromImage(imageData: data! as NSData)
let datos: NSData = NSData(bytes: bytes, length: bytes.count)
newImage = UIImage(data: datos as Data) // Note it's optional. Don't force unwrap!!!

how to create a CStirng from ConstUnsafePointer in Swift

i know CString can init with UnsafePointer ,but how to create it with ConstUnsafePointer
the error of the code: ConstUnsafePointer is not convertible to UnsafePointer
var result:ConstUnsafePointer = sqlite3_column_text(stmt, num)
let cstr:CString = CString(result)
or how to convert it to UnsafePointer
You just need to go through UnsafePointer:
var result: ConstUnsafePointer<UInt8> = sqlite3_column_text(stmt, num)
let cstr: CString = CString(UnsafePointer<UInt8>(result))
Please replace LENGTH with your variable.
var result: ConstUnsafePointer = sqlite3_column_text(stmt, num)
var resultToString: NSString = NSString(bytes: result, length: LENGTH, encoding: NSUTF8StringEncoding)
var cstring: CString = resultToString.UTF8String

Resources