How to decrypt a file in Objective C / IOS that is encrypted in php?

I searched too hard for this error but didn't find anything useful. I am getting a file that is encrypted in php using the following code:

mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $privateencryptkey, base64_encode(file), MCRYPT_MODE_CBC, $hardvector);

      

I cannot decrypt it on IOS. I have tried many libraries such as NSDATA + CommonCrypto, NSFileManager-AES, NSDATA-aes, but I have no success decrypting the file.

Below is the objective-C code:

- (NSData *)AESDecryptWithPassphrase:(NSString *)pass
{
    NSMutableData *ret = [NSMutableData dataWithCapacity:[self length]];
    unsigned long rk[RKLENGTH(KEYBITS)];
    unsigned char key[KEYLENGTH(KEYBITS)];
    const char *password = [pass UTF8String];
    for (int i = 0; i < sizeof(key); i++)
        key[i] = password != 0 ? *password++ : 0;

    int nrounds = rijndaelSetupDecrypt(rk, key, KEYBITS);
    unsigned char *srcBytes = (unsigned char *)[self bytes];
    int index = 0;
    while (index < [self length])
    {
        unsigned char plaintext[16];
        unsigned char ciphertext[16];
        int j;
        for (j = 0; j < sizeof(ciphertext); j++)
        {
            if (index >= [self length])
                break;

            ciphertext[j] = srcBytes[index++];
        }
        rijndaelDecrypt(rk, nrounds, ciphertext, plaintext);
        [ret appendBytes:plaintext length:sizeof(plaintext)];

    }
    return ret;
}

      

This code works well for text, but cannot decrypt files. When I save the decrypted files then it says a file system error. These decrypted files cannot be opened on any system, I think the file format is broken in the process.

I have also tried the following code but with no success:

- (NSData *) decryptedDataUsingAlgorithm: (CCAlgorithm) algorithm
                                     key: (id) key      // data or string
                    initializationVector: (id) iv       // data or string
                                 options: (CCOptions) options
                                   error: (CCCryptorStatus *) error
{
    CCCryptorRef cryptor = NULL;
    CCCryptorStatus status = kCCSuccess;

    NSParameterAssert([key isKindOfClass: [NSData class]] || [key isKindOfClass: [NSString class]]);
    NSParameterAssert(iv == nil || [iv isKindOfClass: [NSData class]] || [iv isKindOfClass: [NSString class]]);

    NSMutableData * keyData, * ivData;
    if ( [key isKindOfClass: [NSData class]] )
        keyData = (NSMutableData *) [key mutableCopy];
    else
        keyData = [[key dataUsingEncoding: NSUTF8StringEncoding] mutableCopy];

    if ( [iv isKindOfClass: [NSString class]] )
        ivData = [[iv dataUsingEncoding: NSUTF8StringEncoding] mutableCopy];
    else
        ivData = (NSMutableData *) [iv mutableCopy];    // data or nil

    [keyData autorelease];
    [ivData autorelease];

    // ensure correct lengths for key and iv data, based on algorithms
    FixKeyLengths( algorithm, keyData, ivData );

    status = CCCryptorCreate( kCCDecrypt, algorithm, options,
                              [keyData bytes], [keyData length], [ivData bytes],
                              &cryptor );

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

    NSData * result = [self _runCryptor: cryptor result: &status];
    if ( (result == nil) && (error != NULL) )
        *error = status;

    CCCryptorRelease( cryptor );

    return ( result );
}

      

The second function from the code above:

- (NSData *) _runCryptor: (CCCryptorRef) cryptor result: (CCCryptorStatus *) status
{
    size_t bufsize = CCCryptorGetOutputLength( cryptor, (size_t)[self length], true );
    void * buf = malloc( bufsize );
    size_t bufused = 0;
    size_t bytesTotal = 0;
    *status = CCCryptorUpdate( cryptor, [self bytes], (size_t)[self length], 
                              buf, bufsize, &bufused );
    if ( *status != kCCSuccess )
    {
        free( buf );
        return ( nil );
    }

    bytesTotal += bufused;

    // From Brent Royal-Gordon (Twitter: architechies):
    //  Need to update buf ptr past used bytes when calling CCCryptorFinal()
    *status = CCCryptorFinal( cryptor, buf + bufused, bufsize - bufused, &bufused );
    if ( *status != kCCSuccess )
    {
        free( buf );
        return ( nil );
    }

    bytesTotal += bufused;

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

      

I haven't been able to resolve this issue for a week ...

+3


source to share


1 answer


It should be noted that the file parameter for mcrypt_encrypt seems to be that the file is base64 encoded before encryption (but that doesn't make any sense), which would imply that you would have to base64 decode after decryption.

Other parameters are straight
forward : MCRYPT_RIJNDAEL_128 is AES, 128 with 128-bit key
MCRYPT_MODE_CBC is cbc mode, default for CommonCrypto.
The padding size for the block size is with null characters, not the standard ones, so the unfinished length issue could be a problem.

No need for you to need another AES method, this is the one I use:



#import <CommonCrypto/CommonCryptor.h>

+ (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;

    return dataOut;
}
// Also add Security.framework to your project.

      

Note that it expects NSData input and padding is specified as standard PKCS.

See CommonCryptor.h

+7


source







All Articles