Files in a file system and items in the keychain are encrypted. After the user unlocks the device, the system generates a password key for decryption through the UDID key and the password set by the user, which is stored in the memory until the device is locked again. Developers can use the Data Protection API to set when files in the file system and items in the keychain should be decrypted. That’s what data protection is all about.

Keychain

The keychain service provides a secure way to store private information (passwords, serial numbers, private keys, certificates, etc.). Each iOS application has an independent keychain. Compared with NSUserDefaults and file saving, a keychain store is more secure, and the information saved in a keychain will not be lost when the APP is deleted.

Based on the characteristics of the key string, we should pay attention to the timing of data deletion when using new data items. Another point to note is the specification of protection properties. If no protection attribute is specified, this is considered a serious security breach.

role

The backup

When we back up the device data, the system will save the user data in the corresponding key chain and according to the corresponding security policy. There are two main categories: encrypted and unencrypted.

The main difference is the scope of data recovery. The encrypted backup data can be restored to any device (except for the item specified by ThisDeviceOnly) while the unencrypted backup data can only be restored to the same device.

Shared

Keychain supports data sharing among multiple applications. But in real world development UIPasteboardNameFind is used instead of keychain. Fortunately, Apple has deprecated it in iOS11. It appears that Apple wants to regulate how developers can share sensitive data, while also reminding people to use more secure ways to store sensitive data.

Use examples

SecItemAdd

NSMutableDictionary *dict = [NSMutableDictionary dictionary];
NSData *passwordData = [@"myPassword" dataUsingEncoding:NSUTF8StringEncoding];

[dict setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass];
[dict setObject:@"Conglomco" forKey:(__bridge id)kSecAttrLabel];
[dict setObject:@"This is your password for the Conglomco service." forKey:(__bridge id)kSecAttrDescription];
[dict setObject:@"chars" forKey:(__bridge id)kSecAttrAccount];
[dict setObject:@"cn.zaker.keychain.sample" forKey:(__bridge id)kSecAttrService];
[dict setObject:passwordData forKey:(__bridge id)kSecValueData];
[dict setObject:(__bridge id)kSecAttrAccessibleWhenUnlocked forKey:(__bridge id)kSecAttrAccessible];

OSStatus error = SecItemAdd((__bridge CFDictionaryRef)dict, NULL);
if (error == errSecSuccess) {
    NSLog(@"Yay");
}
Copy the code

SecItemDelete

NSMutableDictionary *dict = [NSMutableDictionary dictionary];

[dict setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass];
[dict setObject:@"chars" forKey:(__bridge id)kSecAttrAccount];
[dict setObject:@"cn.zaker.keychain.sample" forKey:(__bridge id)kSecAttrService];

OSStatus error = SecItemDelete((__bridge CFDictionaryRef)dict);
if (error == errSecSuccess) {
	NSLog(@"Yay");
}
Copy the code

SecItemUpdate

NSMutableDictionary *dict = [NSMutableDictionary dictionary];
NSData *newPasswordData = [@"newMyPassword" dataUsingEncoding:NSUTF8StringEncoding];

[dict setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass];
[dict setObject:@"chars" forKey:(__bridge id)kSecAttrAccount];
[dict setObject:@"cn.zaker.keychain.sample" forKey:(__bridge id)kSecAttrService];

NSDictionary *updatedAttribute = [NSDictionary dictionaryWithObject:newPasswordData forKey:(__bridge id)kSecValueData];

OSStatus error = SecItemUpdate((__bridge CFDictionaryRef)dict, (__bridge CFDictionaryRef)updatedAttribute);
if (error == errSecSuccess) {
	NSLog(@"Yay");
}
Copy the code

SecItemCopyMatching

NSMutableDictionary *dict = [NSMutableDictionary dictionary];

[dict setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass];
[dict setObject:@"chars" forKey:(__bridge id)kSecAttrAccount];
[dict setObject:@"cn.zaker.keychain.sample" forKey:(__bridge id)kSecAttrService];
[dict setObject:(id)kCFBooleanTrue forKey:(__bridge id)kSecReturnAttributes];

NSDictionary *result = nil;
OSStatus error = SecItemCopyMatching((__bridge CFDictionaryRef)dict, (void *)&result);
if (error == errSecSuccess) {
	NSLog(@"Yay %@", result);
}
Copy the code

Commonly used method

methods describe
SecItemAdd Add data
SecItemDelete Delete the data
SecItemUpdate Modify the data
SecItemCopyMatching To find the data

Protection of property

Key string protects properties meaning
kSecAttrAccessibleAfterFirstUnlock The key is not available after startup until the user first enters the password
kSecAttrAccessibleAlways The key is still available after the device is turned on. It’s deprecated in iOS9
kSecAttrAccessibleAlwaysThisDeviceOnly The key is always available, but cannot be migrated to another device
kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly Role as above
kSecAttrAccessibleWhenUnlocked As long as the device has been unlocked, the key remains available
kSecAttrAccessibleWhenUnlockedThisDeviceOnly Role as above
kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly As above, the password key is available only when the user sets it

KSecAttrAccessibleAlways will introduce an obvious security issue, because of this protection property, as soon as someone steals your device, they can read the contents of the keystring.

KSecAttrAccessibleAfterFirstUnlockThisDeviceOnly this attribute can perfectly solve the security problem. Jailbreaking usually requires a reboot of the device.

KSecAttrAccessibleWhenUnlocked this property requires that the attacker must know the user password to extract data privacy. It’s a good default value for a property.

The protection of the kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly is iOS8 new properties. This property requires that the user set a password when using it, otherwise it will fail.

Basic usage

Item class describe
kSecClassGenericPassword Ordinary password
kSecClassInternetPassword A password used specifically for Internet services
kSecClassCertificate Encryption certificate
kSecClassKey Encryption key
kSecClassIdentity A key pair (including public certificate and private key)

Up to the synchronous

This is a new mechanism introduced in iOS7 that syncs keychain items to iCloud, allowing users to share keychain items across multiple devices.

This mechanism is disabled by default for key chain projects created by applications, but can be enabled by setting kSecAttrSynchronizable to true.

Also note that you cannot specify incompatible kSecAttrAccessible properties when using this option. For example, to specify kSecAttrAccessibleWhenUnlockedThisDeviceOnly doesn’t work, because ThisDeviceOnly specified project not backup, also can’t sync ripped from position, notebook computers, desktop or other synchronization.

Data protection

As an additional layer of protection, Apple has introduced a data protection API that allows developers to specify the lifetime of file decryption keys. You can use this API to control access to files, similar to the kSecAttrAccessible property in the keychain project.

The data protection API uses the user password and the hierarchical key to encrypt the key protecting the files, which is removed from memory when the files cannot be accessed.

File Protection Process

1. The file generates a file key to encrypt the file content.

2. Generate an additional key pair to generate the file public key and file private key.

3. Use the file private key and the Protected Unless Open level public key to calculate a shared password.

4. Use the sha-1 hash value of the shared password to encrypt the file key.

5. The encrypted file key is stored in the metadata of the file, which also contains the public key of the file.

6. The system discards the file private key.

7. Delete the unencrypted file key from the memory when closing the file.

8. When you need to Open the file again, use the Protected Unless Open level private key and the file public key to calculate the shared password.

9. Calculate the SHA-1 hash of the shared password and use it as the key to decrypt the file.

DataProtectionClass permissions

If your application does not need to write or read files when the device is in the background or locked, you can add permissions by configuring an NSFileProtectionComplete value in your project. This will ensure that all the protected file data only when the equipment unlock access, equivalent to set kSecAttrAccessibleWhenUnlocked options for all the application documents.

Starting with Xcode5, new projects will have data protection enabled by default, but some older projects will not be enabled automatically.

The opening mode is shown as follows:

Use examples

NSDataWritingFileProtectionComplete

NSData *data = [self generateData];
NSError *error = nil;
NSString *path = [NSString stringWithFormat:@"%@_demo.pdf", NSTemporaryDirectory()];
[data writeToFile:path options:NSDataWritingFileProtectionComplete error:&error];
if (error) {
	NSLog(@"%@", error);
}
Copy the code

NSFileProtectionComplete

NSString *path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"demo.txt"];
NSError *error = nil;
NSDictionary *attr = [NSDictionary dictionaryWithObject:NSFileProtectionComplete forKey:NSFileProtectionKey];
[[NSFileManager defaultManager] setAttributes:attr ofItemAtPath:path error:&error];
if (error) {
	NSLog(@"%@", error);
}
Copy the code

SQLITE_OPEN_FILEPROTECTION_COMPLETEUNLESSOPEN

NSString *path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"demo.sqlite"];
sqlite3 *handle = NULL;
sqlite3_open_v2([path UTF8String],
                &handle,
                SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE | SQLITE_OPEN_FILEPROTECTION_COMPLETEUNLESSOPEN,
                NULL);
Copy the code

Protection level

CompleteUntilFirstUserAuthentication

This protection level is the default starting with iOS5. It is used to defend against attacks that need to be restarted.

Complete

Officials say this is the most secure level of file protection available. In this case, after the screen is locked, the system removes the hierarchical key from memory and makes the file unreadable.

Examples of specific use are shown above.

Before using Complete protection, consider whether it is appropriate. If your application process is constantly writing/reading a file, this protection mode is not appropriate.

CompleteUnlessOpen

If a file is currently open by an application, this temporarily disables protection for the file. It ensures that open files can be written even if the device is locked and allows new files to be created to disk. However, files with this level of protection cannot be opened when the screen is locked, unless they have been opened before the screen is locked.

CommonCrypto encryption

CommonCrypto is an encryption framework provided by Apple. In the use of this scheme, the main attention to the following problems can be.

Avoid weak algorithms

As we all know, DES is a typical weak algorithm. If you use weak algorithms, your app is vulnerable to password attacks and brute force cracking.

In actual use, we can consider using AES algorithm, MD5 algorithm or MD5 algorithm with salt.

Broken entropy

We usually use the RAND method to generate random numbers, but this random function of the system is not really random. It generates random numbers that conform to normal distribution, which can be obtained using the official provided method SecRandomCopyBytes. You can also use algorithms to generate random numbers.

Here to share a writer before their own implementation of random number cases. Implementation of Uniformly Distributed Random Functions

Weak key

Developers often use the user’s password as an encryption key, especially on mobile devices, which leads to a very fragile, low-entropy encryption key.

The correct pose is then generated using the CCKeyDerivationPBKDF method.

Touch ID

Use examples

#import <LocalAuthentication/LocalAuthentication.h> LAContext *context = [[LAContext alloc] init]; NSError *error = nil; NSString *reason = @"We use this to verify your identify"; if ([context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error]) { [context evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics localizedReason:reason reply:^(BOOL success, NSError * _Nullable error) { if (success) { NSLog(@"Hello, that's your finger! "); } else { NSLog(@"Couldn't read your fingerprint. Falling back to PIN or somthing."); } }]; } else { NSLog(@"Error : %@ %@", error, [error userInfo]); }Copy the code

The security of Touch ID compared to regular passwords

A person’s fingerprint is one of the best passwords in the world. It’s unique, highly specific, and memory-free. It stays with you for life, so you can always use the same fingerprint password.

Than simple 4 digits, one over ten thousand of the lock screen password cracking possibility to find the probability of others in the same individual fingerprint is one over fifty thousand, it is very safe, compared with the former can I keep on trying hard Touch ID fingerprint cracking almost no chance, because there can be no more than fifty thousand people lined up to unlock your device, And Touch ID will refuse the fifth attempt and ask for a password. So we can add more complex passwords instead of simple numeric passwords to further improve security.

Principle of Touch ID fingerprint identification

In such a quick identification, a metal ring on the Home button acts as a finger sensor, notifying Touch ID to read the fingerprint. Inside the button, the Touch ID sensor is only 170 microns thick and has a high resolution of 500 ppi to read tiny fingerprint details. The sensor takes high-resolution images of small parts of the fingerprint in the subderm layer of the skin. It then analyzes this information and sorts the fingerprint according to three basic fingerprint types (arc, dustpan or bucket). It creates details of the pattern that are invisible to the human eye to ensure accurate reading.

Touch ID reads a fingerprint from a 360-degree Angle, then creates some kind of mathematical expression of the fingerprint and compares it to registered data to determine if it matches. If they match, they can unlock the device or pass a token instead of a password.

In addition, according to Apple, Touch ID will continuously add new features to registered fingerprint data, improving matching accuracy and further improving security over time.

In addition to the above, Apple also added some effective measures to ensure further security, such as restarting the device or remaining locked for 48 hours, can only be unlocked with a password rather than a fingerprint.

Secure Enclave

Apple states that the fingerprint pattern is not saved, but is stored on the device as a mathematical representation of the fingerprint characteristics, and that it is not possible to derive a fingerprint image directly from these representations.

The fingerprint verification operation is independent of the main processor chip (such as A7 and A8). The chip has an advanced security architecture called “Secure Enclave” dedicated to the cryptographic fingerprint data, which is encrypted using the Secure Enclave’s private key and managed with a random UID for each startup. Fingerprint data can only be processed and used by Secure Enclave. Because this architecture is independent of other device components, only Touch ID uses it and cannot be used to match other fingerprint databases, so the stored fingerprint data cannot be accessed by iOS or other applications. It’s not stored on Apple servers or backed up to iCloud, for example.

In terms of hardware, the fingerprint data cannot be accessed by components other than the Secure Enclave and Touch ID, and the two chips are isolated from each other, so no software has the right to obtain the fingerprint data and only receives feedback on whether the fingerprint is wrong. Because the core secrets of the architecture are only known to Apple, few third-party applications have access to this sensitive information.

With that, the issue of iOS data protection is over for now. Comments and corrections are welcome.