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


Objective C and PHP generate different encryption result in Blowfish algorithm

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

这是我的目标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''utest.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 ?
}

}

//基于加密结果的64编码格式IOS->8IV/2MGUY0HfwZLrd212fKNyp6AUzYl+

PHP->xUCTX0jsB3XyDWSeyUszSbQ2t90/DNDv

这里编码的结果在两个环境中是不一样的。我试了7天了。但还没有找到解决方案。

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

一点点帮助将不胜感激。谢谢

三元运算符正在毁掉你过去7天的生活

问题是,如果您的iv(iv)?nil:iv.bytesnon-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);

我重新运行您的代码,输出与PHP相同,即xUCTX0jsB3XyDWSeyUszSbQ2t90/DNDv