iOS Serialisation and Encoding
NSCoding and NSSecureCoding
iOS comes with two protocols for object serialisation for Objective-C or NSObject
s: NSCoding
and NSSecureCoding
. When a class conforms to either of the protocols, the data is serialized to NSData
: a wrapper for byte buffers. Note that Data
in Swift is the same as NSData
or its mutable counterpart: NSMutableData
. The NSCoding
protocol declares the two methods that must be implemented in order to encode/decode its instance-variables. A class using NSCoding
needs to implement NSObject
or be annotated as an @objc class. The NSCoding
protocol requires to implement encode and init as shown below.
The issue with NSCoding
is that the object is often already constructed and inserted before you can evaluate the class-type. This allows an attacker to easily inject all sorts of data. Therefore, the NSSecureCoding
protocol has been introduced. When conforming to NSSecureCoding
you need to include:
when init(coder:)
is part of the class. Next, when decoding the object, a check should be made, e.g.:
The conformance to NSSecureCoding
ensures that objects being instantiated are indeed the ones that were expected. However, there are no additional integrity checks done over the data and the data is not encrypted. Therefore, any secret data needs additional encryption and data of which the integrity must be protected, should get an additional HMAC.
Object Archiving with NSKeyedArchiver
NSKeyedArchiver
is a concrete subclass of NSCoder
and provides a way to encode objects and store them in a file. The NSKeyedUnarchiver
decodes the data and recreates the original data. Let's take the example of the NSCoding
section and now archive and unarchive them:
You can also save the info in primary plist NSUserDefaults
:
Codable
It is a combination of the Decodable
and Encodable
protocols. A String
, Int
, Double
, Date
, Data
and URL
are Codable
by nature: meaning they can easily be encoded and decoded without any additional work. Let's take the following example:
By adding Codable
to the inheritance list for the CustomPointStruct
in the example, the methods init(from:)
and encode(to:)
are automatically supported. Fore more details about the workings of Codable
check the Apple Developer Documentation.
You can also use codable to save the data in the primary property list NSUserDefaults
:
JSON Encoding
There are a lot of thrid party libraries to encode data in JSON (like exposed here). However, Apple provides support for JSON encoding/decoding directly by combining Codable
together with a JSONEncoder
and a JSONDecoder
:
XML
There are multiple ways to do XML encoding. Similar to JSON parsing, there are various third party libraries, such as: Fuzi, Ono, AEXML, RaptureXML, SwiftyXMLParser, SWXMLHash
They vary in terms of speed, memory usage, object persistence and more important: differ in how they handle XML external entities. See XXE in the Apple iOS Office viewer as an example. Therefore, it is key to disable external entity parsing if possible. See the OWASP XXE prevention cheatsheet for more details. Next to the libraries, you can make use of Apple's XMLParser
class
When not using third party libraries, but Apple's XMLParser
, be sure to let shouldResolveExternalEntities
return false
.
All these ways of serialising/encoding data can be used to store data in the file system. In those scenarios, check if the stored data contains any kind of sensitive information. Moreover, in some cases you may be able to abuse some serialised data (capturing it via MitM or modifying it inside the filesystem) deserializing arbitrary data and making the application perform unexpected actions (see Deserialization page). In these cases, it's recommended to send/save the serialised data encrypted and signed.
References
Last updated