AQDataExtensions is an
NSData category developed in 2005 by Lucas Newman and distributed with AquaticPrime framework which “allows for easily encrypting and decrypting NSData objects with AES/Rijndael (i.e. the Advanced Encryption Standard)“.
The methods are:
- (NSData*)dataEncryptedWithPassword:(NSString*)password - (NSData*)dataDecryptedWithPassword:(NSString*)password
AQDataExtensions has the following weaknesses:
- Weak key derivation function.
- No authentication.
- Weak random numbers.
Weak key derivation function
As method names indicate, they expect developers to provide a password for encryption. As user-provided passwords may be weak and easily guessed, a computationally expensive function must be used to derive encryption keys from them.
AQDataExtensions derives AES key from password:
// Create the key from first 128-bits of the 160-bit password hash unsigned char passwordDigest; SHA1((unsigned char *)[password UTF8String], strlen([password UTF8String]), passwordDigest); AES_KEY aesKey; AES_set_encrypt_key(passwordDigest, 128, &aesKey);
Unfortunately, it uses SHA-1 hash function, which is very fast and not computationally expensive. This means that weak passwords can be bruteforced more easily.
Data encrypted by
AQDataExtensions is not authenticated, which means that encrypted text can be changed in such a way that after decryption the plain-text will change as well. This is unacceptable for many uses, so authentication must be applied after encryption. For example, you can apply HMAC to encrypted text and append the authenticator to encrypted data. Before decrypting, apply HMAC, and compare the result with the attached authenticator.
Weak random numbers
AQDataExtensions uses CBC encryption mode, it needs random numbers for initialization vector. Random bytes are generated by the following code
srand(time(NULL)); int ivIndex; unsigned char iv; for (ivIndex = 0; ivIndex < 16; ivIndex++) iv[ivIndex] = rand() & 0xff;
rand() function to get them, but
rand() is not suitable for cryptographic purposes. Also, it is predictable in this code because the PRNG is reseeded for each encryption with current time. You should replace this code with
RAND_bytes(iv, 16) from