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