Transitioning to New Encryption Algorithms - ios

How can one transition encrypted data to a new encryption algorithm / settings in an iOS app? I'm not asking exactly how to do this with code, this is rather a conceptual question.
There are currently thousands of people using my iOS app to encrypt their data. I have found issues with the current encryption methods. In order to fix those issues I would need to implement an improved encryption system (see below for details) and transition current users to the new system.
I'm not sure how to go about migrating users to the new system without prompting them to enter their private keys, decrypt, and re-encrypt with the new system. Ideally this transition would be as seamless and as invisible as possible. If the transition does not work I fear that users will lose their data or become frustrated.
Old Encryption Method
AES 256-bit
CBC Mode
New Encryption Method
AES 256-bit
CBC Mode
Password stretching with PBKDF2
Password Salting
Random IV
Hash HMAC
Any ideas on how one could go about transitioning between these two AES encryption systems?

Are the current encryption keys good? If so you can keep them and wrap them with the new key deviation function. That allows the user to change their password without having to re-encrypt the data. If the keys are too weak you will have to decrypt and re-encrypt the data.
I see "Password Salting" and "Hash HMAC", you should be thinking more along the lines of PBKDF2 to create encryption keys from a user supplied password/pass phrase. Use the calibration function to choose the number of rounds.
If you were thinking ahead you have a version indicator and if so can just encrypt new data with the new key-scheme version and have backward compatibility.
I am wondering what Base64 encoding is doing in encryption other than to transport the encrypted data across an interface that can not handle 8-bit bytes such as JSON and XML.

Related

iOS: encrypting file transferred by Airdrop and export compliance

I'm using Airdrop to transfer application internal data between two phones. Because Airdrop was intended for file sharing, it could occur that user choose "save the file" to save the data file in Files app by accident. Since my app is a financial planning app, I'm considering to encrypt the file transferred by Airdrop to keep user's data secure. The encryption only applies to the temp file transferred by Airdrop. Once the app on the receiver phone receivers it, it decrypts the file immediately.
I'm referring to this thread to determine how I should answer the export compliance question if I encrypt the temp file. And I noticed these two exemption items:
(iii) your app uses, accesses, implements or incorporates encryption with key lengths not exceeding 56 bits symmetric, 512 bits asymmetric and/or 112 bit elliptic curve
(iv) your app is a mass market product with key lengths not exceeding 64 bits symmetric, or if no symmetric algorithms, not exceeding 768 bits asymmetric and/or 128 bits elliptic curve.
I don't quite understand the difference between the conditions in the two items (what is a mass market product?). But I don't think either helps, because the ciphers provided by iOS Cryptokit contains only AES and ChaChaPoly - the former takes a minimum key size of 128 bits and the latter takes 256 bits key size.
Since there are a lot of apps using Airdrop to transfer application internal data (I can tell that from the discussions on SO), I wonder how other people deal with this? Is this considered an exemption case?
BTW, I considered other options, but none is satisfying:
Don't encrypt the data. Obscure it instead (for example, using something like Caesar cipher). But that feels very unprofessional.
Don't use Airdrop. Implement my own data transfer mechanism. For example, start a tiny web server on sender side and the receiver side get the data through HTTPS, which from my understanding is an exemption case. I don't choose this approach because a) Airdrop provides a much better user experience than this approach, b) I'll need to use Bonjour to discover service, which requires local network permission. I'd like to avoid that if possible.
The answer depends on what cipher you use to encrypt the data.
Apple summarises your requirements in a couple of documents.
First, in the CryptoKit documentation
Typically, the use of encryption that’s built into the operating system—for example, when your app makes HTTPS connections using URLSession—is exempt from export documentation upload requirements, whereas the use of proprietary encryption is not. To determine whether your use of encryption is considered exempt, see Determine your export compliance requirements.
This leads you to this document which has a table, that I have shown in part:
Assuming that you use AES from Apple's Crypto Kit framework, the second clause would apply. You don't need to provide any documentation to Apple but you should submit a self classification report to the us government.
The exemptions you listed in your question do not apply since you wouldn't use a symmetric cipher with a key length of 64 or 56 bits.

Use a AWS KMS AES-GCM key with AES-CBC algorithm from iOS CommonCrypto

As far as I can tell, AWS KMS Data Keys are AES-GCM keys.
(source: https://d0.awsstatic.com/whitepapers/KMS-Cryptographic-Details.pdf page 13)
Does that mean I must use AES-GCM to encrypt data with them or will a AES-CBC algorithm work too? I am trying to use these KMS keys to encrypt data on iOS without including external dependencies.
I found CommonCrypto, and wrote some code that seems to work with the KMS data keys, but as far as I know CommonCrypto only supports AES-CBC.
I also can't seem to write working code in any language to then decrypt the cipher text generated. Is this because the output of my GCM key + CBC algorithm is garbage? Why doesn't my encryption code complain?
Also, is it possible to do AES-GCM encryption on iOS without CryptoKit?
AES-GCM internally uses CTR mode, which turns a block cipher into a stream cipher and doesn't need padding. AES-GCM mode is an authenticated encryption mode which provides not only confidentiality but also, integrity and authentication.
CBC mode whereas requires padding and it is removed from TLS. Outdated and highly problematic, BEAST, bit flipping attack, padding oracle attacks, etc.
note: GCM is not perfect. GCM IV reuse is can be catastrophic.
GCM and CBC are completely different encryption schemes. You cannot decrypt an AES-GCM encrypted ciphertext with AES-CBC vice-versa. You can put any block cipher instead of AES in the previous sentence.
You have to stick the same encryption algorithm and schemes.
As stated in AWS documenation
All symmetric key encrypt commands used within HSMs use the Advanced Encryption Standards (AES) 4, in Galois Counter Mode (GCM) [5] using 256- bit keys. The analogous calls to decrypt use the inverse function.
You have to use AES-GCM.

Strategy for generating and saving password for encryption and decryption

I'm using the RNEncryptor and RNDecryptor classes for encryption and decryption as follows:
NSData *encryptedData = [RNEncryptor encryptData:input
withSettings:kRNCryptorAES256Settings
password:thePassword
error:nil];
NSData *output = [RNDecryptor decryptData:encryptedData
withSettings:kRNCryptorAES256Settings
password:thePassword
error:nil];
The first time I have to encrypt data in my app I generate a password using the RNCryptor class as follows:
NSData *thePasswordData = [RNCryptor randomDataOfLength:32];
NSString *thePassword = [aesPasswordData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
I save this generated password in the app's Keychain and use it for all subsequent encryption and decryption.
Is this a good strategy for encryption/decryption or can anyone see any flaws in it? Should I instead be generating an AES key and storing that in the Keychain and working with that rather than a password?
Edit: I changed above how I generate the password from using the NSProcessInfo class to using the RNCryptor class based on Rob Napier's answer. That aside I'm still curious to know whether the strategy in general of working with a password rather than an AES key is correct and secure.
This is not a good way to pick a password. globallyUniqueString can be quite predictable in many of its bits. You're much better off using something like RNCryptor.randomDataOfLength to generate a blob of desired length (32 bytes would be ideal), and then base-64 encode it to get a password.
Using randomDataOfLength to generate keys instead wouldn't really be any more secure, but it would be faster (by 10s of milliseconds depending on the device, if that matters to you). In general, I recommend using the password interface unless you have a special problem where keys are particularly helpful. Keys are just a little harder to use correctly.
The actual encryption key used by these libs is derived from the password, if you use one, but, IIRC, salted so it isn't intrinsically less secure.
There are concerns regarding the theoretical level of security provided by these libraries, (see How to correctly encrypt data with proper authentication using AES-256-CBC in php?) but you have to make a judgement call on that. Thing to bear in mind is that RNCryptor is a set of libraries (which may have published attack vectors in different implementations) AND a consistent format, which is useful if you want to move encrypted data across platforms.
Personally, I would feel more comfortable with using a unique, random AES key for each encryption and storing that key encrypted with RSA stored in the keychain.

Partial encryption using AES - IOS application

I would like to apply the encryption & decryption technique in one my downloading concept. I want to do the partial encryption using AES 256. Is it possible to do it? is it have any algorithms available for partial encryption&decryption.
Please suggest ideas.
Partial Encryption : it means i dont want to encrypt the full content of the file.It will do the encryption for some specified part of file.(like 10% or 20%) or some junks of file content. basically , I dont want to do the encryption to the entire content
THanks.
I'm not aware of any algorithms that offer "partial encryption" functionality. Instead, I think you'll need to take charge of separating out the bytes you wish to encrypt and pass that through standard AES encryption code.

Confusion about Encryption in iOS

I'm a very newb programmer trying to write some iOS programs, and when I reached the part where I must encrypt my data, I ran into a misty and ill-documented wall. Apple apparently provides all the tools one needs to encrypt data but doesn't write about it anywhere. Currently I am experimenting with stuff found in https://github.com/AlanQuatermain/aqtoolkit, which apparently work. However, I read in http://robnapier.net/blog/aes-commoncrypto-564 that one should not use user selected passwords as encryption keys, but I have seen a few examples of people using the user's password directly with this library and others. Does this apply here, and should I run the user password through a small hurdle race before using it?
It is a good idea to use the hash of a password as a key for your crypto routines. One reason for that is that different algorithms may need keys of a different length and by selecting the appropriate hashing algorithm (e.g. SHA256 for AES256) you automatically get a key with the appropriate length.

Resources