user1400286
user1400286

Reputation:

AES Decryption using ObjectiveC

I use following code to decrypt a file encrypted, the file was encrypted using a JAVA application.

Cipher.h file

#import <Foundation/Foundation.h>
#import <CommonCrypto/CommonCryptor.h>
#import <CommonCrypto/CommonDigest.h>

@interface Cipher : NSObject {
    NSString *cipherKey;
}

@property (retain) NSString *cipherKey;

- (Cipher *) initWithKey:(NSString *) key;

- (NSData *) encrypt:(NSData *) plainText;
- (NSData *) decrypt:(NSData *) cipherText;

- (NSData *) transform:(CCOperation) encryptOrDecrypt data:(NSData *) inputData;  

+ (NSData *) md5:(NSString *) stringToHash; 

@end

Cipher.m file

#import "Cipher.h"

@implementation Cipher 

@synthesize cipherKey;

- (Cipher *) initWithKey:(NSString *) key {  
    self = [super init];  
    if (self) {  
        [self setCipherKey:key];  
    }  
    return self;  
} 

- (NSData *) encrypt:(NSData *) plainText {  
    return [self transform:kCCEncrypt data:plainText];  
}  

- (NSData *) decrypt:(NSData *) cipherText {  
    NSData *returnData = [[NSData alloc] init];
    returnData = [self transform:kCCDecrypt data:cipherText];

    return returnData;  
}  

- (NSData *) transform:(CCOperation) encryptOrDecrypt data:(NSData *) inputData {  

    // kCCKeySizeAES128 = 16 bytes  
    // CC_MD5_DIGEST_LENGTH = 16 bytes  
    NSData* secretKey = [Cipher md5:cipherKey];  

    CCCryptorRef cryptor = NULL;  
    CCCryptorStatus status = kCCSuccess;  

    uint8_t iv[kCCBlockSizeAES128];  
    memset((void *) iv, 0x0, (size_t) sizeof(iv));  

    status = CCCryptorCreate(encryptOrDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,  
                             [secretKey bytes], kCCKeySizeAES128, iv, &cryptor);  

    if (status != kCCSuccess) {  
        return nil;  
    }  

    size_t bufsize = CCCryptorGetOutputLength(cryptor, (size_t)[inputData length], true);  

    void * buf = malloc(bufsize * sizeof(uint8_t));  
    memset(buf, 0x0, bufsize);  

    size_t bufused = 0;  
    size_t bytesTotal = 0;  

    status = CCCryptorUpdate(cryptor, [inputData bytes], (size_t)[inputData length],  
                             buf, bufsize, &bufused);  

    if (status != kCCSuccess) {  
        free(buf);  
        CCCryptorRelease(cryptor);  
        return nil;  
    }  

    bytesTotal += bufused;  

    status = CCCryptorFinal(cryptor, buf + bufused, bufsize - bufused, &bufused);  

    NSLog(@"Status-3: %d", status);
    if (status != kCCSuccess) {
        free(buf);  
        CCCryptorRelease(cryptor);  
        return nil;  
    }  
    bytesTotal += bufused;  

    CCCryptorRelease(cryptor);  

    return [NSData dataWithBytesNoCopy:buf length:bytesTotal];  
}  

+ (NSData *) md5:(NSString *) stringToHash {  

    const char *src = [stringToHash UTF8String];  

    unsigned char result[CC_MD5_DIGEST_LENGTH];  

    CC_MD5(src, strlen(src), result);  

    return [NSData dataWithBytes:result length:CC_MD5_DIGEST_LENGTH];  
} 

@end

This is how I decode the encrypted data:

- (void)viewDidLoad
{
    [super viewDidLoad];

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory1 = [paths objectAtIndex:0];
    NSString *getImagePath = [documentsDirectory1 stringByAppendingPathComponent:@"Blue.jpg"];
    NSData *objNSData1 = [NSData dataWithContentsOfFile:getImagePath];

    Cipher *objCipher= [[Cipher alloc] initWithKey:@"1234567891234567"];

    NSData *decryptedData = [[NSData alloc] init];

    decryptedData = [objCipher decrypt:objNSData1];

    NSLog(@"%@", decryptedData);

    myImage.image = [UIImage imageWithData:decryptedData];

}

Decryption isn't working successfully and it returns 4304 error.

Upvotes: 1

Views: 3492

Answers (1)

Rob Napier
Rob Napier

Reputation: 299663

I know this was generated by Java code. If you have any control over that code, then you should understand that the protocol it's using is highly insecure. It does not correctly generate a key (MD5 is not a good PBKDF), and does not correctly generate an IV. Coupled with the lack of an HMAC, it is subject to several kinds of attack. See Properly encrypting with AES with CommonCrypto for full details on on how to set these correctly, and RNCryptorenter link description here for an example implementation.

To your specific issue, are you having trouble decrypting things that this encrypted, or are you having trouble decrypting things that the Java encrypted? It's possible that you have a mismatch with the Java.

You should check whether the error is coming in the Update or Final step. If the Update step, then you've configured something incorrectly. If the Final step, you should start by making sure your padding is correct. The end of the document should be PKCS#7 padding. That means that it should end with one of the following sequences (unless the decrypted size is exactly divisible by 16):

01
02 02
03 03 03
04 04 04 04
...

The final size of the entire encrypted data should be divisible by 16.

Upvotes: 2

Related Questions