【问题标题】:Objective C and PHP generate different encryption result in Blowfish algorithmObjective C 和 PHP 在 Blowfish 算法中生成不同的加密结果
【发布时间】:2015-11-04 18:28:17
【问题描述】:

我正在尝试使用 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_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端?

我们将不胜感激。 谢谢。

【问题讨论】:

  • Blowfish,尽管它的名字很酷,但不应该用于新工作,它不被认为是安全的。新作品应该使用 AES。
  • 我投票保持开放,但强烈建议您编辑它作为调试结果。 (我以前经历过 n 平台加密/解密,所以我感到你很痛苦,但是......)提供一个完整的例子,在两个平台上输入相同,记录中间结果并突出差异的第一点。跨度>
  • "编辑它的调试结果" ?请详细解释一下好吗?

标签: php ios objective-c cocoa-touch blowfish


【解决方案1】:

Ternary operator 正在毁掉你过去 7 天的生活。

问题是如果你的ivnon-nil (iv)?nil:iv.bytes,你正在传递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

【讨论】:

  • @datta 考虑接受有用的答案。要接受答案,请单击最佳答案旁边的空心复选标记,这样做会提高您的声誉并提供更多功能,请参阅reputation faq 更多详细信息,请参阅this page。另外请考虑返回并接受过去的答案,这样做会增加您的声誉并允许更多功能,请参阅reputation faq
猜你喜欢
  • 1970-01-01
  • 2015-05-07
  • 2013-09-16
  • 2014-02-14
  • 2011-01-22
  • 2011-01-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多