swift gzip data to string issue - ios

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".

Related

iOS 13 AES decrypt with Crypto Swift not working

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.

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.

Convert BLE 4.0 data into usable information using Swift (iOS)

This is my first BLE project using swift and would greatly appreciate any direction you guys have out there. My arduino is using a red bear lab BLE mini to send integers (between 1 and 1200) from a sensor to my iPhone app. I am able to find and connect to the device and transfer the data. I, at least for the past three days, cannot figure how to convert that data back to usable information.
For example in the didUpdateValueForCharacteristic function if I print:
print(characteristic.value!.bytes)
I get a return that looks like:
0x000000013cdb5f80
If I were to print characteristic.value! I would get something that looked like:
<hc>
It seems that I've read everything on the internet about this and still cannot figure out how to get this reading back to the integer being sent. It would be greatly appreciated if someone would be willing to give me some guidance here.
Thanks in advance!
UPDATE: Based on the feedback I'm posting some code that I've used but is not returning what I need. I've attempted to turn the value into an integer using the following:
var out : NSInteger = 0
let data = NSData(bytes: characteristic.value!.bytes, length: sizeof(NSInteger))
data.getBytes(&out, length: sizeof(NSInteger))
print("Integer: \(out)")
This returns the integer 64816. I'm expecting a number between 0 and 1200 so this is either wrong or I'm missing a step.
I've also attempted to turn the data into a string using:
var string1 = NSString(data: characteristic.value!, encoding: NSUTF8StringEncoding) as! String
print("String: \(string1)")
This just unwraps a nil value and crashes.
First confirm they type of object being returned. The value property is of NSData type, so you can use the following code to convert it to NSString.
- (id)initWithData:(NSData *)data encoding:(NSStringEncoding)encoding
Finally after three days of struggling I figured this out. Answer had nothing to do with the swift code. Instead my baud rate on the arduino was too slow. Increasing this solved everything.

compare two secKey (public keys) in ios Swift

I want to ssl public key pinning in swift, I read lot of examples how to do that, last think who I can't find is How to compare two public keys in SecKey object format.
Example:
let serverPublicKey = SecTrustCopyPublicKey(secTrust) /*return SecKey object from actual SecTrust*/
let clientPublicKey = getLocalPublicKeyFromDer() /*return SecKey from .der local*/
how to compare them? At now I do that and it works:
if(serverPublicKey! as AnyObject).isEqual(clientPublicKey){
/*Key is the same, pinning OK!*/
}
find it way on gitHub: https://github.com/teamcarma/IOS-AlamofireDomain/blob/master/Source/ServerTrustPolicy.swift
but is cast to AnyObject a good idea? How to work isEqual on casted SecKey? Can any explain me?
ps.
Another idea is getting base64 from SecKey - I try and it also works, but it require a KeyChain temp operations and look no profesional.
Cited from the headers:
"Most SecKeychainItem functions will work on an SecKeyRef."*
You may cast SecKeyRef to a SecKeychainItem. If this is a valid operation (that is, the key is a keychain item), you may apply function
SecKeychainItemCreatePersistentReference
and get a CFData object, filled with attributes and data. Then check with memcpyon the bytes or cast it to a NSData object and check with isEqualToData. Don't forget to release the CFData object.
Edit
On iOS, as far as I known, the only reliable approach is to copy the data (or secret) into the keychain, using a temporary key, so that you can find it again, and then extract the data. It's cumbersome, but if you just implement it in a minimalistic way, it should not take more than 30 lines of code. I have a working example.
I The usual disclaimer: Use this at your own risk, and always be careful with security stuff.
iOS10 added:
CFDataRef _Nullable SecKeyCopyExternalRepresentation(SecKeyRef key, CFErrorRef *error)
so you can now create two Data (NSData) objects, then compare those.
Have a look at this answer for just getting the NSData: Can I get the modulus or exponent from a SecKeyRef object in Swift?
You can then compare the two NSData instances using isEqualToData:
I don't have expereince in the domain, but if they are two strings (irrespectiveof their content), you would basically do a simple check:
if(string1 == string2)
{
//condition logic
}

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.

Resources