This question already has answers here:
Is it possible to use AES128 with GCM mode on iOS?
(3 answers)
Closed 6 years ago.
Currently the encryption mode supported with AES 256 is CBC. But I want to use AES 256 encryption with GCM mode along with PKCS5Padding / PKCS7Padding.
Do let me know how it can be done ?
Common Crypto does not support GCM. But there is an implementation of AES GCM in the Security.framework, and you can add your own header file to use it. However associated data (AEAD) does not work.
From SO Answer by soyer:
CCCryptorStatus CCCryptorGCM(
CCOperation op, // kCCEncrypt, kCCDecrypt
CCAlgorithm kCCAlgorithmAES,
const void *key, size_t keyLength,
const void *iv, size_t ivLen,
const void *aData, size_t aDataLen, // does not work
const void *dataIn, size_t dataInLength,
void *dataOut,
const void *tag, size_t *tagLength);
There is an implemntation AES GCM on github that seems reasonable albiet slow in comparison to Common Crypto. Use at your own risk.
Related
We need to encrypt a request using AES128 in Android and IOS and then send that encrypted message in the backend server written in Java.
Our Android encryption code is like below:
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
where keyspec and ivspec is random bytes generated.
In Objective-C, this is how we do the encryption.
NSString* iv = #"a12bc1256b4de9a0";
NSData* ivData = [iv dataUsingEncoding:NSUTF8StringEncoding];
NSMutableData* cipherData = [NSMutableData dataWithLength:data.length+kCCBlockSizeAES128];
CCCryptorStatus result = CCCrypt(kCCEncrypt, kCCAlgorithmAES, kCCOptionPKCS7Padding, keyData.bytes, keyData.length, ivData.bytes, data.bytes, data.length, cipherData.mutableBytes, cipherData
.length, &outLength);
The problem with this is that when we compare the encrypted byte of thee Java program and Objective-C, they are not the same. I understand that the CCOption parameter in Objective-C should be CBC but that is not in the enum list of the CommonCrypto library. When we set it 0, the encrypted byte only return a series of zeros.
Please suggest other alternatives on how to do the AES 128 encryption in Objective-C using AES/CBC/NOPadding Algorithm.
You've requested padding: kCCOptionPKCS7Padding. That's not the same thing as Java's NoPadding. Remove the padding option. (You can use 0 to mean "no options.")
It's also unclear whether every other part of your encryption it the same. You didn't include the key generation or IV in the Java code.
(Note that if you get the exact same bytes out of an encryption algorithm for the same message, then you're using the encryption algorithm in an insecure way. Secure encryption constructions will generate a different cipher text for every encryption. I understand that your server may be using this kind of insecure approach; it's a very common mistake. But it is insecure.)
I'm trying to do RSA2048 in iOS and am following the example codes from Apple and also this question RSA implementations in Objective C. I have tested on iPhone 5c with iOS 8.4.1, but the sample codes fail at decryption with private key, with error code -9809 (An underlying cryptographic error was encountered), even though encryption with public key. I understand the basic approach is to generate an RSA key pair, secure them in keychain and use public key ref to encrypt and private key to decrypt. I'm completely lost why decryption shall fail, and not always, there are times when decryption succeeded.
Full codes can be found at https://gist.github.com/aceisScope/372e6d6f92650ce03624. The decryption part that throws an error is below, where from time to time status = -9809, and other times it works and returns 0:
status = SecKeyDecrypt(privateKey,
PADDING,
cipherBuffer,
cipherBufferSize,
plainBuffer,
&plainBufferSize
);
I have also set a check that if such key pair has already generated, next time encryption/decryption is called, it will directly using the already-generated-and-stored key pair from key chain without generating a new pair.
Update:
I came across this post iPhone Public-Key Encryption SecKeyEncrypt returns error 9809 (errSSLCrypto) which found out wrong cipher buffer size may cause -9809 error to encryption. Yet even if I make sure both the cipher buffer size in encryption and plain buffer size in decryption is the same as key block size and private key block size, encryption always works but with decryption failing from time to time.
I found the problem. By the end of encryption, when converting cipher buffer to NSData, in the following code
NSMutableData *data=[[NSMutableData alloc] init];
[data appendBytes:cipherBuffer length:strlen( (char*)cipherBuffer ) + 1];
the length is not correct. It should be the size of the cipher buffer, which is the same as key block size.
So after changing it to
NSData *data = [NSData dataWithBytes:cipherBuffer length:cipherBufferSize];
decryption works now.
I'm using AES encryption to encrypt / decrypt user's info in my app.
This is the code I'm using:
https://gist.github.com/matsuda/9204276
Everything works just fine.
But the code got scanned for security vulnerability recently and there's an issue that got flagged.
The vulnerability:
Signed Memory Arithmetic
Description:
The software reads or writes to a buffer using an index or pointer that references a memory location after the end of the buffer.
Line 39-40 of NSData+AES.m of the code in the above link is where it got highlighted
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
I'm not sure what I should do.
The buffer size is calculated with dataLength + kCCBlockSizeAES128 just before allocation so the length should be okay?
Thanks for your help in advance.
My question is about this question:
Is your product designed to use cryptography or does it contain or incorporate cryptography?
I don't know what to answer because my app is using the commoncrypto framework and md5 encryption. What should I answer?
Codes used in App:
(NSString *) md5:(NSString *) input
{
const char *cStr = [input UTF8String];
unsigned char digest[16];
CC_MD5( cStr, strlen(cStr), digest ); // This is the md5 call
NSMutableString *output = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
for(int i = 0; i < CC_MD5_DIGEST_LENGTH; i++)
[output appendFormat:#"%02x", digest[i]];
return output;
}
md5 is a hash function and hash functions are one-way and are not encryption.
If all you are using is a hash function the answer is No you are not using encryption.
If you are using AES, DES of other encryption, that is two-way crypto functions then the answer is YES.
Merely adding the CommonCrypto framework makes no difference, it is the usage of encryption that counts.
The only concern is any encryption in the app, there is no concern with anything done on a related server.
iTunes Connect does not care server-side implementation.
If you use MD5 or any other encryption mechanism in server side (but not in App side), you should choose No for the answer.
I have implemented publickey privatekey RSA encryption in iOS application based on the examples provided on the Apple Developer site.
It works perfectly if I encrypt and return the uint8_t cipherBuffer, and then decrypt from the uint8_t cipherBuffer. However I need to store the encrypted data to an .xcdata model as NSData.
The problem I'm having is reliably converting the uint8_t cipherBuffer to NSData and/or converting the NSData back to uint8_t when it's time to decrypt. The decrypted data appears to be truncated.
This is how I'm converting the uint8_t encrypted buffer to NSData:
return [NSData dataWithBytesNoCopy:cipherBuffer length:BUFFER_SIZE];
This is how I'm converting the encrypted NSData back to a uint8_t buffer when it is time to decrypt it:
uint8_t *cipherBuffer = (uint8_t*)[cipherText bytes];
Thanks jgh and Jody;
I changed the encryption method to "malloc" the buffer and tried several approaches to write the bytes to NSData, wound up with:
return [NSData dataWithBytes:(const void *)cipherBuffer length:CIPHER_BUFFER_SIZE];
What finally fixed the issue was changing the way I was creating the uint8_t in the decryption method:
const uint8_t *cipherBuffer = (const uint8_t*)[data bytes];
Without seeing how you're creating cipherBuffer, it's difficult to say exactly why it's not working. However, from the documentation on dataWithBytesNoCopy:
The returned object takes ownership of the bytes pointer and frees it on deallocation. Therefore, bytes must point to a memory block allocated with malloc.
If you're just declaring cipherBuffer as
uint8_t cipherBuffer[BUFFER_SIZE];
it may explain your problems. Instead, use malloc:
uint8_t* cipherBuffer = malloc(BUFFER_SIZE);
It sounds like you are giving it a raw pointer, then re-using that pointer.
dataWithBytesNoCopy: wants to keep the pointer you give it. In fact, you must give it a pointer that you created with malloc, because it will free it when it's done with the data.
If you do not want the NSData object to take ownership, you should use dataWithBytesNoCopy:length:freeWhenDone:.