Objective C和PHP在Blowfish算法中生成不同的加密结果

Objective C and PHP generate different encryption result in Blowfish algorithm

我正在尝试使用 CBC 模式和 kCCOptionPKCS7Padding 填充来实现 Blowfish 算法。场景 like 在 IOS(Objective C) 和 PHP 两个系统之间进行编码和解码。 但是,加密结果在两个平台上是不一样的。

这是我的 objective C 源代码。

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

编码和解码功能在 Xcode 中运行良好。

这是PHP代码。

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 ?
}

}

// 加密结果base64编码格式 IOS -> 8IV/2MGUY0HfwZLrd212fKNyp6AUzYl+

PHP -> xUCTX0jsB3XyDWSeyUszSbQ2t90/DNDv

此处编码结果在两个环境中不相同。我从过去 7 天开始尝试。 但是还没有找到解决方案。

到目前为止我知道 CCCrypt 用于 CBC 模式。我不明白我的问题在哪里。 是 PHP 结束还是 IOS 结束?

我们将不胜感激。 谢谢。

Ternary operator 毁了你过去 7 天的生活。

问题是如果你的 iv(iv)?nil:iv.bytes

non-nil,你就超过了 nil

它应该是 (iv)?iv.bytes:nil 或简单的 iv.bytes 因为向 nil 对象发送消息完全没问题

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);

将上面改为下面

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