Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Objective C and PHP generate different encryption result in Blowfish algorithm

I am trying to implement Blowfish algorithm with CBC mode and kCCOptionPKCS7Padding padding . Scenario like performs encoding and decoding between two systems like IOS(Objective C) and PHP. But, Encryption result are not same in two platform .

Here is my objective C source code .

ViewController.m

#import "ViewController.h"
#import <CommonCrypto/CommonCryptor.h>
@interface ViewController ()
@end
@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    // configure paremetre
    NSData *IV  =  [@"aaaaaaaa" dataUsingEncoding:NSUTF8StringEncoding];// Constant IV 
    NSError *error;
    NSData *key = [@"37501370571307510" dataUsingEncoding:NSUTF8StringEncoding]; // Constant Key
    NSString *stringOriginal = @"Did you decrypt it ?";
    NSData *dataOriginal = [stringOriginal dataUsingEncoding:NSUTF8StringEncoding];;
    // Encryption
    NSData *dataEncrypted = [self doBlowfish:dataOriginal
                                     context:kCCEncrypt
                                         key:key
                                     options:kCCOptionPKCS7Padding
                                          iv:IV
                                       error:&error];

    NSString *encryptedBase64String = [dataEncrypted base64EncodedStringWithOptions:0];
    // Decryption
    NSData *dataToDecrypt = [[NSData alloc] initWithBase64EncodedString:encryptedBase64String options:0];
    NSData *dataDecrypted = [self doBlowfish:dataToDecrypt
                                     context:kCCDecrypt
                                         key:key
                                     options:kCCOptionPKCS7Padding
                                          iv:IV
                                       error:&error];

    NSString *stringDecrypted = [[NSString alloc] initWithData:dataDecrypted encoding:NSUTF8StringEncoding];
    NSLog(@"stringDecrypted %@", stringDecrypted); // Did you decrypt it ?
    NSLog(@"encryptedBase64String  %@", encryptedBase64String);// 8IV/2MGUY0HfwZLrd212fKNyp6AUzYl+

}

// Blowfish Encryption and Decryption
- (NSData *)doBlowfish:(NSData *)dataIn
               context:(CCOperation)kCCEncrypt_or_kCCDecrypt
                   key:(NSData *)key
               options:(CCOptions)options
                    iv:(NSData *)iv
                 error:(NSError **)error
{
    CCCryptorStatus ccStatus   = kCCSuccess;
    size_t          cryptBytes = 0;
    NSMutableData  *dataOut    = [NSMutableData dataWithLength:dataIn.length + kCCBlockSizeBlowfish];

    ccStatus = CCCrypt( kCCEncrypt_or_kCCDecrypt,
                       kCCAlgorithmBlowfish,
                       options,
                       key.bytes,
                       key.length,
                       (iv)?nil:iv.bytes,
                       dataIn.bytes,
                       dataIn.length,
                       dataOut.mutableBytes,
                       dataOut.length,
                       &cryptBytes);

    if (ccStatus == kCCSuccess) {
        dataOut.length = cryptBytes;
    }
    else {
        if (error) {
            *error = [NSError errorWithDomain:@"kEncryptionError"
                                         code:ccStatus
                                     userInfo:nil];
        }
        dataOut = nil;
    }
    return dataOut;
}
@end

the encoding and decoding functionalities Working fine in Xcode .

Here is PHP code .

crypt.php

<?php
class Crypt {

    public $Algo;
    public $Mode;
    public function __construct()
    {
        $this->Algo = MCRYPT_BLOWFISH;
        $this->Mode = MCRYPT_MODE_CBC;
    }
    public function ivGenerator()
    {
        $ivSize = mcrypt_get_iv_size($this->Algo, $this->Mode);
        $iv = mcrypt_create_iv($ivSize, MCRYPT_RAND);
        return base64_encode($iv);
    }
    public function encrypt($data, $key, $iv)
    {
        $iv = base64_decode($iv);
        $blockSize = mcrypt_get_block_size($this->Algo, $this->Mode);
        $pkcs = $blockSize - (strlen($data)%$blockSize);
        $data .= str_repeat(chr($pkcs), $pkcs);
        $encrypt = mcrypt_encrypt($this->Algo, $key, $data, $this->Mode, $iv);
        return rtrim(base64_encode($encrypt));
    }
    public function decrypt($data, $key, $iv)
    {
        $encrypt = base64_decode($data);
        $iv = base64_decode($iv);
        $decrypt = mcrypt_decrypt($this->Algo, $key, $encrypt, $this->Mode, $iv);
        //$pad = ord($decrypt[($len = strlen($decrypt)) - 1]);
        //return substr($decrypt, 0, strlen($decrypt) - $pad);
        return $decrypt;
    }
}
?>

final_encryption_test.php

public function __construct() 
{
    parent::__construct();
    date_default_timezone_set('Asia/Dhaka');    
    $this->load->helper('url');
    $this->load->library('crypt');
}

public function index()
{
    $iv = base64_encode("aaaaaaaa"); // same IV as IOS
    $key = "37501370571307510"; // Same key 
    $data = "Did you decrypt it ?"; // same plain text

    echo "Plain Text >> " . $data; 
    echo "<br>";

    $enc = $this->crypt->encrypt($data, $key, $iv);// Output -> xUCTX0jsB3XyDWSeyUszSbQ2t90/DNDv which is not same with objective c result
    echo "Enc text >> " . $enc;
    echo "<br>";


    $dec = $this->crypt->decrypt($enc, $key, $iv);
    echo "Dec text >> " . $dec; // Result will -> Did you decrypt it ?
}

}

// Encryption result base64encoding format IOS -> 8IV/2MGUY0HfwZLrd212fKNyp6AUzYl+

PHP -> xUCTX0jsB3XyDWSeyUszSbQ2t90/DNDv

Here Encoded result is not same in two enviornment . I am trying it from last 7 days . But do not find a solution yet .

So far I know CCCrypt is used for CBC mode . I did not understand where is my problem . Is it PHP end or IOS end ?

A little help will be much appreciated. Thanks.

like image 854
Shourob Datta Avatar asked Nov 04 '15 08:11

Shourob Datta


1 Answers

Ternary operator is ruining your life from the last 7 days.

The problem is you are passing nil if your iv is non-nil at (iv)?nil:iv.bytes

Either it should be (iv)?iv.bytes:nil or simple iv.bytes because it's perfectly okay to send message to a nil object

ccStatus = CCCrypt(kCCEncrypt_or_kCCDecrypt,
                   kCCAlgorithmBlowfish,
                   options,
                   key.bytes,
                   key.length,
                   (iv)?nil:iv.bytes,  //This is ruining your life
                   dataIn.bytes,
                   dataIn.length,
                   dataOut.mutableBytes,
                   dataOut.length,
                   &cryptBytes);

Change above to below

ccStatus = CCCrypt(kCCEncrypt_or_kCCDecrypt,
                   kCCAlgorithmBlowfish,
                   options,
                   key.bytes,
                   key.length,
                   iv.bytes,
                   dataIn.bytes,
                   dataIn.length,
                   dataOut.mutableBytes,
                   dataOut.length,
                   &cryptBytes);

I re-run your code and the output is the same as PHP i.e. xUCTX0jsB3XyDWSeyUszSbQ2t90/DNDv

like image 65
Inder Kumar Rathore Avatar answered Sep 21 '22 20:09

Inder Kumar Rathore