Reputation: 51
I am trying to implement AES encryption with Fixed Key and IV in Objective c and C#, when i encrypt in C# and try to decrypt in Objective C it is not working. Can you please check and let me know what i am doing wrong.
C# Code
byte[] strKey = Convert.FromBase64String("CAshKUlVCllbEwPmzS4cTg==");
byte[] strIV = Convert.FromBase64String("HDAxBBlsKyVeIuS63kdCjg==");
byte[] strOutput = EncryptStringToBytes_Aes("satishsatyam", strKey, strIV);
string strOutput1 = ByteToString(strOutput);//i6BMzAlcnz6Z5dQKWkio7A==
static byte[] EncryptStringToBytes_Aes(string plainText, byte[] Key, byte[] IV)
{
byte[] encrypted;
// Create an Aes object
// with the specified key and IV.
using (Aes aesAlg = Aes.Create())
{
aesAlg.Mode = CipherMode.ECB;
aesAlg.Padding = PaddingMode.PKCS7;
aesAlg.KeySize = 256;
aesAlg.BlockSize = 128;
// Create an encryptor to perform the stream transform.
ICryptoTransform encryptor = aesAlg.CreateEncryptor(Key, IV);
// Create the streams used for encryption.
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
//Write all data to the stream.
swEncrypt.Write(plainText);
}
encrypted = msEncrypt.ToArray();
}
}
}
return encrypted;
}
private string ByteToString(byte[] objByte)
{
string strOutput = Convert.ToBase64String(objByte);
return strOutput;
}
Objective C
//
// CryptLib.h
//
#import <CommonCrypto/CommonDigest.h>
#import <CommonCrypto/CommonCryptor.h>
#import <UIKit/UIKit.h>
@interface CryptLib : NSObject
- (NSData *)encrypt:(NSData *)plainText key:(NSString *)key iv:(NSString *)iv;
- (NSData *)decrypt:(NSData *)encryptedText key:(NSString *)key iv:(NSString *)iv;
- (NSData *)generateRandomIV:(size_t)length;
- (NSString *) md5:(NSString *) input;
- (NSString*) sha256:(NSString *)key length:(NSInteger) length;
@end
#import "CryptLib.h"
#import "NSData+Base64.h"
@implementation CryptLib
-(NSData *)decrypt:(NSData *)encryptedText key:(NSString *)key iv:(NSString *)iv {
char keyPointer[kCCKeySizeAES256+2],// room for terminator (unused) ref: https://devforums.apple.com/message/876053#876053
ivPointer[kCCBlockSizeAES128+2];
BOOL patchNeeded;
patchNeeded = ([key length] > kCCKeySizeAES256+1);
if(patchNeeded)
{
NSLog(@"Key length is longer %lu", (unsigned long)[[[CryptLib alloc] md5:key] length]);
key = [key substringToIndex:kCCKeySizeAES256]; // Ensure that the key isn't longer than what's needed (kCCKeySizeAES256)
}
[key getCString:keyPointer maxLength:sizeof(keyPointer) encoding:NSUTF8StringEncoding];
[iv getCString:ivPointer maxLength:sizeof(ivPointer) encoding:NSUTF8StringEncoding];
if (patchNeeded) {
keyPointer[0] = '\0'; // Previous iOS version than iOS7 set the first char to '\0' if the key was longer than kCCKeySizeAES256
}
NSUInteger dataLength = [encryptedText length];
//see https://developer.apple.com/library/ios/documentation/System/Conceptual/ManPages_iPhoneOS/man3/CCryptorCreateFromData.3cc.html
// For block ciphers, the output size will always be less than or equal to the input size plus the size of one block.
size_t buffSize = dataLength + kCCBlockSizeAES128;
void *buff = malloc(buffSize);
size_t numBytesEncrypted = 0;
//refer to http://www.opensource.apple.com/source/CommonCrypto/CommonCrypto-36064/CommonCrypto/CommonCryptor.h
//for details on this function
//Stateless, one-shot encrypt or decrypt operation.
CCCryptorStatus status = CCCrypt(kCCDecrypt,/* kCCEncrypt, etc. */
kCCAlgorithmAES128, /* kCCAlgorithmAES128, etc. */
kCCOptionPKCS7Padding, /* kCCOptionPKCS7Padding, etc. */
keyPointer, kCCKeySizeAES256,/* key and its length */
ivPointer, /* initialization vector - use same IV which was used for decryption */
[encryptedText bytes], [encryptedText length], //input
buff, buffSize,//output
&numBytesEncrypted);
if (status == kCCSuccess) {
return [NSData dataWithBytesNoCopy:buff length:numBytesEncrypted];
}
free(buff);
return nil;
}
#import "ViewController.h"
#import "CryptLib.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
libr = [[CryptLib alloc]init];
NSString *inputString = @"sample testing"; // this is the text that you want to encrypt.
NSLog(@"inputString : %@", inputString); //print the inputString text
NSString * _key = @"shared secret"; //secret key for encryption. To make encryption stronger, we will not use this key directly. We'll first hash the key next step and then use it.
// _key = [[CryptLib alloc] sha256:_key length:32]; //this is very important, 32 bytes = 256 bit
_key = @"CAshKUlVCllbEwPmzS4cTg==";
NSLog(@"_key data:: %@", _key); //print the _key text
// NSString * iv = [[[libr generateRandomIV:11] base64EncodingWithLineLength:0] substringToIndex:16]; //Here we are generating random initialization vector (iv). Length of this vector = 16 bytes = 128 bits
NSString * iv = @"HDAxBBlsKyVeIuS63kdCjg==";
NSLog(@"iv data:: %@", iv); //print the iv text
NSData *encryptedData = [libr decrypt:[@"i6BMzAlcnz6Z5dQKWkio7A==" dataUsingEncoding:NSUTF8StringEncoding] key:_key iv:iv];
NSString * decryptedText = [[NSString alloc] initWithData:encryptedData encoding:NSUTF8StringEncoding];
NSLog(@"decrypted data:: %@", decryptedText); //print the decrypted text
}
Any Sample code for cross platform for ios/Android,c#
Upvotes: 3
Views: 1985
Reputation: 112865
The first step is to log all input and output just before and after the encryption call in hex so it can be verified the same.
Also verify that all parameters are the same and correct, this may require reading the documentation to determine the defaults.
The actual encryption function is rather simple, just a function call, nothing really mysterious to get working,just get the input correct.
You are not supplying the same parameters to the C# and ObjC code. C# is ECB mode and ObjC is CBC mode (the default).
Use CBC mode.
The key Base64: "CAshKUlVCllbEwPmzS4cTg=="
is hex 080B212949550A595B1303E6CD2E1C4E
which is 16 bytes.
In C# and ObjC you are stating the key size as 256-bits (32-bytes): aesAlg.KeySize = 256;
and kCCKeySizeAES256
respectively.
Specify the key size as 128-bits for a 128-bit key.
In the ObjC code you are not Base64 decoding the key and iv.
There is no reason to use a 3rd party Base64 library.
Updated with example code, no error checking: not for production:
// First convert Base64 strings to data
NSString *stringIn = @"satishsatyam";
NSData *dataIn = [stringIn dataUsingEncoding:NSUTF8StringEncoding];
NSData *iv = [[NSData alloc] initWithBase64EncodedString:@"HDAxBBlsKyVeIuS63kdCjg==" options:0];
NSData *key = [[NSData alloc] initWithBase64EncodedString:@"CAshKUlVCllbEwPmzS4cTg==" options:0];
// Encryption
size_t encryptBytes = 0;
NSMutableData *encrypted = [NSMutableData dataWithLength:stringIn.length + kCCBlockSizeAES128];
CCCrypt(kCCEncrypt,
kCCAlgorithmAES,
kCCOptionPKCS7Padding, // CBC is the default mode
key.bytes, kCCKeySizeAES128,
iv.bytes,
dataIn.bytes, dataIn.length,
encrypted.mutableBytes, encrypted.length,
&encryptBytes);
encrypted.length = encryptBytes;
NSLog(@"encrypted hex: %@", encrypted);
NSLog(@"encrypted Base64: %@", [encrypted base64EncodedStringWithOptions:0]);
// Decryption
size_t decryptBytes = 0;
NSMutableData *decrypted = [NSMutableData dataWithLength:encrypted.length];
CCCrypt(kCCDecrypt,
kCCAlgorithmAES,
kCCOptionPKCS7Padding, // CBC is the default mode
key.bytes, kCCKeySizeAES128,
iv.bytes,
encrypted.bytes, encrypted.length,
decrypted.mutableBytes, decrypted.length,
&decryptBytes);
decrypted.length = decryptBytes;
NSLog(@"decrypted in hex: %@", decrypted);
NSLog(@"decrypted string: %@", [[NSString alloc] initWithData:decrypted encoding: NSUTF8StringEncoding]);
Output:
encrypted as hex: cbdb58fe ad464126 ea90252b 2ff52276
encrypted Base64: y9tY/q1GQSbqkCUrL/Uidg==
decrypted as hex: 73617469 73687361 7479616d
decrypted string: satishsatyam
Upvotes: 2