Objective C and PHP generate different encryption result in Blowfish algorithm
Asked Answered
H

1

9

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.

Hydrophobic answered 4/11, 2015 at 8:14 Comment(3)
Blowfish, despite it's cool name, should not be used for new work, it is not considered secure. New work should use AES.Ritzy
I'm voting to leave open, but strongly suggest you edit it the result of debugging. (I've been through n-platform encrypt/decrypt before, so I feel your pain, but...) provide a complete example with the same inputs on both platforms, log intermediate results and highlight the fist point of difference.Winger
"edit it the result of debugging" ? would you explain me details please ?Hydrophobic
F
4

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

Foreclose answered 4/11, 2015 at 9:53 Comment(1)
@datta Consider accepting answers that are helpful. To accept an answer click on the hollow checkmark next to the answer that is best, doing so will increase your reputation and allow more capabilities, See reputation faq See this page for more detail. Also please consider going back and accepting past answers, doing so will increase your reputation and allow more capabilities, See reputation faqRitzy

© 2022 - 2024 — McMap. All rights reserved.