iOS 13 AES decrypt with Crypto Swift not working - ios

I have an app which uses AES256 decryption for authentication. For this I use the Crypto Swift library.
Until now it always worked, but with iOS 13 coming out, the decryption does not work.
Here's the code I use for decryption:
func aesDecrypt(key: String) throws -> String {
let data = Serializer.hexaToBytes(self)
let key = Serializer.hexaToBytes(key)
let decrypted = try! AES(key: key, blockMode: ECB(), padding: .pkcs7).decrypt(data)
let decryptedData = Data(decrypted)
return String(bytes: decryptedData.bytes, encoding: .utf8) ?? "Could not decrypt"
}
String(bytes: decryptedData.bytes, encoding: .utf8) always returns nil...
Why could that be and what should I do to make it working again?
Any help would be appreciated :)

The most common cause of these kinds of problems is that somewhere you're using Data.description to compute a hex string. That was never correct, but it was possible to get away with it prior to iOS 13. In iOS 13, the format was changed (the format was never promised to stay the same), and that's broken lots of things that relied on it being stable.
The next thing I'd check is Serializer.hexaToBytes to make sure it's correctly implemented and returning what you expect.
Given that this particular function is written in way that doesn't carefully check for errors (and uses a very dangerous mode like ECB), it likely that related functions are similarly uncareful with errors. Check each to see if it's returning the values you're expecting.

Related

swift gzip data to string issue

I use gzip library to convert data to gzip data
If I want to get string from data I do String(data: data, encoding: .utf8) . But if I do the same for gzip data I get nil string, because as far as I understand it's impossible to convert gzip data to string with .utf8 encoding.
I need that because I want to compare data with a server developer (because he sometimes he says that my data is incorrect format, but sometimes it's ok, and that's strange because I use the same library, and I have thoughts that may be the problem is on server side).
Is there any way to convert gzip data to any string to compare it then later?
If this is just for debug purpose, then I think the quickest way is:
let myGZipNSData = myGZipData as! NSData //I wrote a "!" just for the sample)
print("myGZipNSData: \(myGZipNSData)")
It should output:
myGZipNSData: <5b226d79 41727261 7956616c 75653022 2c226d79 41727261 7956616c 75653122 5d>
This relies on -description method of NSData which print "<hexValue>".
Do not rely on it on release version, almost never rely on -description (yes, Apple could change the behavior of -description in next release. It happened on a different class).
Other way (safer) to get almost the same result, you can check this question: How to convert Data to hex string in swift which you get you the same result (almost, less space, and no </>) as the previous one.
Other way: Base 64
Use base64EncodedString() method of Data:
let base64Str = myGZipData?.base64EncodedString()
print("base64Str: \(base64Str!)")
Output:
base64Str: WyJteUFycmF5VmFsdWUwIiwibXlBcnJheVZhbHVlMSJd
Now, there should be other way:
Have a array representation with Int values (between 0/255 instead of hex), but it seems to be for debug purpose so check if you can "reproduce the current solutions" (working/fast implementation) I gave you, and check with the server developer what he/she can do on his/her side too to compare.
Note:
For the purpose of this sample, myGZipData is constructed this way:
let array = ["myArrayValue0", "myArrayValue1"]
let myGZipData = try? JSONSerialization.data(withJSONObject: array, options:[])
It's not really a GZipData, but the goal was to quickly have a Data object "big enough".

Convert NSString to JSON

I am converting a [NSDictionary] to NSString like so :
do{
let newDict = try NSJSONSerialization.dataWithJSONObject(objectDictionaries, options: NSJSONWritingOptions.PrettyPrinted)
if let json = NSString(data: newDict, encoding: NSUTF8StringEncoding) {
print(json)
}
When the json prints out I get this:
How do I convert this NSString to JSON without changing the format as this photo shows?
The I want to send this json to a API and the format I want is the only one the API will be able to encode,
Remove the option NSJSONWritingOptions.PrettyPrinted in the call to dataWithJSONObject. That is what is forcing the outputted string to be formatted like that.
The output of NSJSONSerialization.dataWithJSONObject is valid JSON, and that's what you should send to an API. Conversion to a string is pointless unless you want to view the output for debugging purposes.
NSJSONWritingOptions.PrettyPrinted is useful if you want to view the output for debugging purposes, but otherwise it's just a waste of time and makes the JSON a few percent bigger which takes memory, time to send to the API, time to process in the API.
PS. If "Pretty printed" or not makes any difference to your API, then your API is pretty badly broken.

Reading Websites in iOS

I am trying to read data from my API. I am not using JSON data because the API doesn't return an array, just a line of text. Anyways, I am using the following code to read the text from the API.
func contactVetApi(url:String){
let nsUrl = NSURL(string:url)
let task = NSURLSession.sharedSession().dataTaskWithURL(nsUrl!){
(data, response, error) in
print(data)
}
task.resume()
}
I am calling this function in the ViewDidLoad function of my ViewController file. As you can see, it takes a parameter that is a string. The parameter is the URL to read. It then translates the string into a NSUrl so it can be used with the sharedSession. I then initialize the shared session and create a data task with that url. I then print out the data it returns. The only issue is that the output isn't what I am expecting. What I am expecting is for it to say, "Future home of something quite cool." Although, this is what I am getting.
Optional(<46757475 72652068 6f6d6520 6f662073 6f6d6574 68696e67 20717569 74652063 6f6f6c>)
Optional(<46757475 72652068 6f6d6520 6f662073 6f6d6574 68696e67 20717569 74652063 6f6f6c>)
I need help figuring out why it is printing that out instead of what I am expecting. In case it is needed, the api url is http://apis.wilsonfamily5.org/vet/about.php. Before anybody asks though, I did add into the info.plist file the disabling of the iOS 9 app transport security. If you need any extra information to help me solve this problem, I would be more then happy to give it to you. I want to thank you in advance.
You currently are printing a NSData object, which will always look like that jibberish. What you actually want however is to convert the NSData to a NSString or String to create a human readable form:
var dataAsString = NSString(data: data, encoding: NSUTF8StringEncoding)
Taken from this answer.

Can I turn a string into a block of code in swift?

Is there any way to turn a string into a block of code? I'm making an Ajax request to a website of mine that has an endpoint that returns some swift code as a string. I can get that code back as a string, but I can't run that code because it doesn't know that it is code.
As others have pointed out, if you are creating an iOS app (especially for distribution on the app store), you can not do this. However, if you are writing Swift code for an OS X machine AND you know that XCode is installed on the machine, you can run your Swift code string by running the command-line Swift compiler. Something like this (with proper error checking, of course):
var str = "let str = \"Hello\"\nprintln(\"\\(str) world\")\n"
let task = Process()
task.launchPath = "/usr/bin/swift"
let outpipe = Pipe()
let inpipe = Pipe()
inpipe.fileHandleForWriting.write(str.data(using: String.Encoding.utf8, allowLossyConversion: true)!)
task.standardInput = inpipe
task.standardOutput = outpipe
task.launch()
task.waitUntilExit()
task.standardInput = Pipe()
let data = outpipe.fileHandleForReading.readDataToEndOfFile()
let output = NSString(data: data, encoding: String.Encoding.utf8.rawValue)! as String
Again, this is probably not recommended in nearly all real-world cases, but is a way you can execute a String of Swift code, if you really need to.
No, you can't do that. Swift is a compiled language, not interpreted like Ajax.
The Swift compiler runs on your Mac, not on the iOS device. (The same is true for Objective-C).
Plus, Apple's app store guidelines forbid delivering executable code to your apps, so even if you figured out a way to do it, your app would be rejected.
Edit:
Note that with the advent of Swift playgrounds, it is possible to run the Swift compiler on an iPad. Recent high-end iPhones are probably also up to the job, but you'd have to figure out how to get it installed.
As stated above though, Apple's app store guidelines forbid you from delivering code to your apps at runtime.

iOS SecKeyEncrypt OAEP SHA512

From what I can tell looking through the various padding values for the SecKeyEncrypt method in Apple's security framework, it does not support OAEP padding with a SHA512 hash digest. In fact, I can't seem to determine if the SecKeyEncrypt method does any sort of hashing/masking of each block during the CBC process.
Herein lies my problem. All my other platforms (PHP, Android, .NET) use RSA with OAEP padding and a SHA512 digest.
For example: In C# we can use BouncyCastle's OaepEncoding class which accepts any Digest and performs the hash/mask operation during the block cipher encryption process. In php, the phpseclib project provides the same functionality.
And finally, my question... can this same functionality be achieved on iOS by somehow using a hybrid of "manual" hashing and using SecKeyEncrypt? Or am I missing something much more obvious here.
Cheers!
EDIT: I think I could probably hash/mask each block by porting the bouncy castle code and then pass the new byte array to SecKeyEncrypt for encrpytion, but that begs the question, does SecKeyEncrypt do that already using some other hashing algo internally?
As of iOS 10.0, the .rsaEncryptionOAEPSHA512 option has been added as a SecKeyAlgorithm.
Swift 4
let attributes: [String: Any] = [ ... ]
let pk = SecKeyCreateRandom(attributes as CFDictionary, nil)!
let pub = SecKeyCopyPublicKey(pk)!
let message = "Encrypt me".data(using: .utf8)!
var error: Unmanaged<CFError>?
let cipherText = SecKeyCreateEncryptedData(pub, .rsaEncryptionOAEPSHA512, message as CFData, &error)
It appears this is not possible native to the Security framework for iOS. I have had a ton of issues getting OAEP RSA encryption to work properly cross platform.
However, I did just hear from a third party library provider, Chillkat, that they are adding support for this. See: http://www.chilkatforum.com/questions/7778/ios-rsa-encryption-using-oaep-sha512
EDIT: I installed Chilkat's library and had it working in minutes.

Resources