Search code examples
c#iosencryptionaescommoncrypto

Decrypt a base64 string using C# generated by iOs CCCrypt function using AES


Could someone please help decrypt the base64 string generated by iOS code below into its C# equivalent.

I am trying to end up with "Meet me at the secret location at 8pm" within c#.

iOS generated the following encryption: qd+SGaij5KSBScuLs3TpJS/3Dew8fHTudcs/5MG7Q1kqcrZzZycMgTcQuEEEED5f

This iOS code successfully encrypts and decrypts data as required within XCode 6.

Thank you in advance for your help and support.

Darren

#import <CommonCrypto/CommonCryptor.h>

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    NSString *sData = @"Meet me at the secret location at 8pm";
    NSString *sIv = @"4QesEr03HwE5H1C+ICw7SA==";
    NSString *sKey = @"ovA6siPkyM5Lb9oNcnxLz676K6JK6FrJKk4efEUWBzg=";

    NSData *dData = [sData dataUsingEncoding:NSUTF8StringEncoding];
    NSData *dIv = [sIv dataUsingEncoding:NSUTF8StringEncoding];
    NSData *dKey = [sKey dataUsingEncoding:NSUTF8StringEncoding];

    NSData *dEncrypt = [self doCipher:dData iv:dIv key:dKey context:kCCEncrypt];

    NSData *dDecrypt = [self doCipher:dEncrypt iv:dIv key:dKey context:kCCDecrypt];
    NSString *sDecrypt = [[NSString alloc] initWithData:dDecrypt encoding:NSUTF8StringEncoding];
    NSLog(@"Decrypted Data: %@",sDecrypt);
}

- (NSData *)doCipher:(NSData *)dataIn
              iv:(NSData *)iv
             key:(NSData *)symmetricKey
         context:(CCOperation)encryptOrDecrypt
{
    CCCryptorStatus ccStatus   = kCCSuccess;
    size_t          cryptBytes = 0;    // Number of bytes moved to buffer.
    NSMutableData  *dataOut    = [NSMutableData dataWithLength:dataIn.length + kCCBlockSizeAES128];

    ccStatus = CCCrypt( encryptOrDecrypt,
                   kCCAlgorithmAES128,
                   kCCOptionPKCS7Padding,
                   symmetricKey.bytes,
                   kCCKeySizeAES128,
                   iv.bytes,
                   dataIn.bytes,
                   dataIn.length,
                   dataOut.mutableBytes,
                   dataOut.length,
                   &cryptBytes);

    if (ccStatus != kCCSuccess) {
        NSLog(@"CCCrypt status: %d", ccStatus);
    }

    dataOut.length = cryptBytes;

    NSString *base64 = [dataOut base64EncodedStringWithOptions:0];
    NSLog(@"%@",base64);

    return dataOut;
}

Solution

  • The given base64 string qd+SGaij5KSBScuLs3TpJS/3Dew8fHTudcs/5MG7Q1kqcrZzZycMgTcQuEEEED5f is a two way pack.

    First it has to be base64 decoded (which is easy in C#) and afterwards it has to be decrypted by using the correct algorithm. From the given parameters it hopefully uses the AES or Rijndael algorithm (example code here) where you have to put in the base64 decoded bytes, the key and the IV.

    After that you hopefully get out your desired data.

    So i wrote an example on myself and i'm able to encrypt and decrypt the specified message with C#.

    But the retrieved encrypted message differs from the iOS generated message:

    Your iOS message: qd+SGaij5KSBScuLs3TpJS/3Dew8fHTudcs/5MG7Q1kqcrZzZycMgTcQuEEEED5f My C# message: wC2dn+QVhOhf+NqZVskopLdh2XDAdG3SmczrKF+TjQsGfxu07BEhRdiDqkbGY80O

    I just made some little changes and dit a little deeper look. One thing i see is that you say in your iOS code that the key has a length of 256 bit. But the key you are providing has only a length of 128 bit. It seems that C# in that case simply switches back to 128 bit key length (cause changing the key size in the code below doesn't change the encrypted bytes). But maybe the CCCrypt in iOS makes something different. So either adopt in your iOS code the key size or provider a 256 bit key and than compare the results of iOS and C# again.

    Example:

    var message = @"Meet me at the secret location at 8pm";
    var iv = @"4QesEr03HwE5H1C+ICw7SA==";
    var key = @"ovA6siPkyM5Lb9oNcnxLz676K6JK6FrJKk4efEUWBzg=";
    
    byte[] encryptedBytes;
    
    using (var aesCryptoProvider = new AesCryptoServiceProvider())
    {
        aesCryptoProvider.BlockSize = 128;
        aesCryptoProvider.KeySize = 256;
        aesCryptoProvider.IV = Convert.FromBase64String(iv);
        aesCryptoProvider.Key = Convert.FromBase64String(key);
        aesCryptoProvider.Padding = PaddingMode.PKCS7;
        aesCryptoProvider.Mode = CipherMode.CBC;
    
        using (var encryptor = aesCryptoProvider.CreateEncryptor())
        using (var memoryStream = new MemoryStream())
        using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
        using (var streamWriter = new StreamWriter(cryptoStream, Encoding.UTF8))
        {
            streamWriter.Write(message);
            streamWriter.Close();
            encryptedBytes = memoryStream.ToArray();
        }
    }
    
    var encryptedMessage = Convert.ToBase64String(encryptedBytes);
    Console.WriteLine(encryptedMessage);
    
    using (var aesCryptoProvider = new AesCryptoServiceProvider())
    {
        aesCryptoProvider.BlockSize = 128;
        aesCryptoProvider.KeySize = 256;
        aesCryptoProvider.IV = Convert.FromBase64String(iv);
        aesCryptoProvider.Key = Convert.FromBase64String(key);
        aesCryptoProvider.Padding = PaddingMode.PKCS7;
        aesCryptoProvider.Mode = CipherMode.CBC;
    
        using (var decryptor = aesCryptoProvider.CreateDecryptor())
        using (var memoryStream = new MemoryStream(Convert.FromBase64String(encryptedMessage)))
        using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
        using (var streamReader = new StreamReader(cryptoStream, Encoding.UTF8))
        {
            Console.WriteLine(streamReader.ReadToEnd());
        }
    }