2

I want to generate the same encrypted string in iOS, android in .net. I can generate same string android and in .net but different for Objective C.

Android code:

public static String encrypt(String key, String value) {
    try {
        SecretKey secretKey = new SecretKeySpec(key.getBytes(), "AES");
        AlgorithmParameterSpec iv = new IvParameterSpec(key.getBytes());
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
        return new String(Base64.encode(cipher.doFinal(value.getBytes("UTF-8")), Base64.NO_WRAP));

    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

backend code

public Encryption(input: string): any {

return CryptoJS.AES.encrypt(CryptoJS.enc.Utf8.parse(input), this.Cryptokey,

{

    keySize: 128 / 8,

    iv: this.iv,

    mode: CryptoJS.mode.CBC,

    padding: CryptoJS.pad.Pkcs7

});

} and in Objective C code

- (NSData *)AES256EncryptWithKey:(NSString *)key

{

// 'key' should be 32 bytes for AES256, will be null-padded otherwise
char keyPtr[kCCKeySizeAES256+1]; // room for terminator (unused)
bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding)

// fetch key data
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];

NSUInteger dataLength = [self length];

//See the doc: For block ciphers, the output size will always be less than or
//equal to the input size plus the size of one block.
//That's why we need to add the size of one block here
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);

size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
                                      keyPtr, kCCKeySizeAES256,
                                      NULL /* initialization vector (optional) */,
                                      [self bytes], dataLength, /* input */
                                      buffer, bufferSize, /* output */
                                      &numBytesEncrypted);
if (cryptStatus == kCCSuccess) {
    //the returned NSData takes ownership of the buffer and will free it on deallocation
    return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
}

free(buffer); //free the buffer;
return nil;

}

and I followed these URLs Encrypt AES/CBC/PKCS7Padding

How to encrypt with AES 256 CBC in Objective C

AES CBC Encryption With PKCS7Padding Has Different Results In Java And Objective-C

As per my understanding for Objective C first I need to convert the password in NSData then pass it to the AES encryption method. This method will return to me encrypted Data now I need to convert this in base 64 string encoding. Can anyone suggest to me what should I do to generate the same result for iOS, Android, and .net?

For example if I want to encrypt string "xceedancce" in all 3 platforms and my key is 7061737323313233

then in Android and .net the result is "uXDlYA4e8Z8HWd9rvNdXaw==" same but in iOS

it is "l4zDDnwOVJ0dz2fl7HdKIA==" Can anyone suggest what should I do in Objective C?

Thank you.

Chandni
  • 692
  • 1
  • 10
  • 25
  • Just arguing as I'm not familiar with objective-c but in Java you use the key.getBytes as input for your IV, in objective-c you set the iv to 'NULL' that seems to be wrong. Maybe you can use 'keyPtr' as well ? – Michael Fehr Aug 28 '20 at 12:53
  • Thank you @MichaelFehr I tried to provide same iv in both in Android and in Objective C but getting different result. – Chandni Aug 29 '20 at 01:35
  • @zaph can you please help me in this thank you. – Chandni Aug 29 '20 at 11:07
  • This encryption is incredibly insecure. It's reusing the IV, uses the key as the IV, incorrectly generates the key, and the key is the wrong length for the requested encryption. Please do not use this code if you can possibly replace it. I built RNCryptor on a ton of platforms specifically because people make these mistakes so often. The reason you don't get what you expect, though, is that you're passing a different IV (as Michael notes), and you pass a 128-bit "key" (not really a key) but then ask for 256-bit encryption (kCCKeySizeAES256). You meant kCCKeySizeAES128. – Rob Napier Aug 31 '20 at 14:08
  • If all your encryptions generate the same output for the same plaintext and key, then you know that your system is insecure. By design, crypto systems inject some random data, such as the IV, so that the same message+key will create different outputs every time. The whole point of the IV in AES-CBC is to be an extra random value. – Rob Napier Aug 31 '20 at 14:11
  • Thank you @RobNapier I have already tried RNCryptor but couldn't get the same value from my Objective C code so I started to try different ways. Actually I will encrypt the password which will decrypt by backend and send response success and user can be login in the app. If you have any other way to encrypt pwd in iPhone and decrypt the password in .net to get the same result. please share. Thank you. – Chandni Sep 01 '20 at 08:05
  • RNCryptor will do exactly that. Every time you encrypt, the output will be different. That's by design and is a critical security feature. But the output will be decrypted correctly using the .net version of RNCryptor. – Rob Napier Sep 01 '20 at 14:46
  • Thank you @RobNapier I start to work for it. – Chandni Sep 02 '20 at 02:21
  • @RobNapier - Can you please share some URL or code base which work compatible for iOS objective C and RNCryptor-cs. I found proper description for iOS objective C by this URL https://github.com/RNCryptor/RNCryptor-objc but couldn't get proper information by this https://github.com/RNCryptor/RNCryptor-cs for C# Can you please suggest me. – Chandni Sep 02 '20 at 06:47

1 Answers1

3

Thank you, Rob. I used the RNCryptor library for both (Objective C and C#) and it solved my problem.

Here is my code for Objective C:

-(NSString *)encryptUsingRNCryptor:(NSString *)strPassword{

NSData *data = [strPassword dataUsingEncoding:NSUTF8StringEncoding];
NSError *error;
NSData *encryptedData = [RNEncryptor encryptData:data
                                    withSettings:kRNCryptorAES256Settings
                                          password:kKeyForEncryption
                                             error:&error];
NSString *encryptString = [encryptedData base64EncodedStringWithOptions:0];

NSLog(@"enccrypted data ----->>>## %@ ## %@", encryptedData, encryptString);

// Decryption

NSData *decryptedData = [RNDecryptor decryptData:encryptedData
                                    withPassword:kKeyForEncryption
                                           error:&error];
NSString *decodedString = [[NSString alloc] initWithData:decryptedData encoding:NSUTF8StringEncoding];

NSLog(@" Decryted data ----%@ --------and string %@", decryptedData, decodedString);

return [encryptedData base64EncodedStringWithOptions:0];

}

and for C# decryption we used RNCryptor-cs library.

Once again thank you Rob :)

Chandni
  • 692
  • 1
  • 10
  • 25