This is my java code. Now I want to implement same functionality in Objective-C.
Cipher encryptCipher;
IvParameterSpec iv = new IvParameterSpec(key);
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
encryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
encryptCipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
byte[] encrypted = encryptCipher.doFinal(dataToEncrypt.getBytes());
Log.d("TAG", "encrypted string:"
+ Base64.encodeToString(encrypted, Base64.DEFAULT));
return Base64.encodeToString(encrypted, Base64.DEFAULT).trim();
This is my iOS implementation
- (NSData *)AES256EncryptWithKey:(NSString*)key
{
char keyPtr[kCCKeySizeAES256 + 1];
bzero(keyPtr, sizeof(keyPtr));
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
NSUInteger dataLength = [self length];
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void* buffer = malloc(bufferSize);
size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,
kCCAlgorithmAES128,
kCCOptionPKCS7Padding,
keyPtr,
kCCKeySizeAES256,
NULL,
[self bytes],
dataLength,
buffer,
bufferSize,
&numBytesEncrypted);
if (cryptStatus == kCCSuccess)
{
return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
}
free(buffer);
return nil;
}
This is my hash key generating function. this function return same key in android and ios
int dkLen = 16;
NSData *keyData = [hash_key dataUsingEncoding:NSUTF8StringEncoding];
NSData *salt = [saltKey dataUsingEncoding:NSUTF8StringEncoding];
uint rounds = 1000;
uint keySize = kCCKeySizeAES128;
NSMutableData *derivedKey = [NSMutableData dataWithLength:keySize];
CCKeyDerivationPBKDF(kCCPBKDF2, // algorithm
keyData.bytes, // password
keyData.length, // passwordLength
salt.bytes, // salt
salt.length, // saltLen
kCCPRFHmacAlgSHA1, // PRF
rounds, // rounds
derivedKey.mutableBytes, // derivedKey
dkLen*8);
return derivedKey;
I am getting a different output. I am doing anything wrong?.please help me to find out.
Well, how big is your key?
kCCAlgorithmAES128
andkCCKeySizeAES256
assume different key sizes. I'm assuming that you're using a 16 byte key, because your Java code would throw an exception otherwise. If you're using a 128 bit key, then you should usekCCKeySizeAES128
.Additionally, you're not passing in any IV, so it will be assumed that the IV is filled with 0x00 bytes, but in Java, you're using the key as IV.
Don't use the key as IV. That diminishes the use of the IV in the first place that is there to randomize the ciphertext. You need to generate a random IV for each encryption and send it along with the ciphertext, for example by prepending it to the ciphertext.
Yes, PKCS#5 padding and PKCS#7 padding are the same thing.
One problem is that the Java code used CBC mode, the iOS code used ECB mode.
Next, from the referenced project:
//result= yHbhApwTpQ2ZhE97AKF/g==
is invalid Base64, it does not contain a multiple of 4 bytes.
With these options: CBC, PKCS#7 padding
This is the test code:
This is the encryption method (in the class
TestClass
):Note: I keep separate the encryption and data conversions. Conflating them just makes testing more complicated.
If you use an on-line encryption implementation the padding will probably not be PKCS#7 because mcrypt does not support it, instead it does non-standard null padding. Since the pad bytes are just the count of pad bytes the padding can be simulated in the input. Here is an example using AES – Symmetric Ciphers Online
Note that "hello" PKCS#7 padded to a block size of 16 bytes adds 11 bytes of the uint8 value 11 or
0x0B
:68656c6c6f0B0B0B0B0B0B0B0B0B0B0B
.Finally the question remains why the Java code does not produce this result?