我试图解决的情况:在我的 Cocoa 应用程序中,我需要使用对称密码加密一个字符串,将其发布到 PHP,并让该脚本解码数据。该过程需要反向工作以返回答案(PHP 编码,Cocoa 解码)。
我遗漏了一些东西,因为即使我可以在 PHP 和 Cocoa 中使密钥和初始化向量 (iv) 相同,但当一个应用程序将其编码数据发送到另一个应用程序时,解码永远不会起作用。两者都可以很好地编码/解码自己的数据(经过验证以确保手头没有一些 PEBKAC 问题)。我怀疑某处存在填充问题,我只是没有看到。
我的 cocoa 应用程序使用 SSCrypto 进行编码(它只是 OpenSSL 函数的一个方便的包装器)。密码是 Blowfish,模式是 CBC。(请原谅内存泄漏,代码已被剥离为基本要素)
NSData *secretText = [@"secretTextToEncode" dataUsingEncoding:NSUTF8StringEncoding];
NSData *symmetricKey = [@"ThisIsMyKey" dataUsingEncoding:NSUTF8StringEncoding];
unsigned char *input = (unsigned char *)[secretText bytes];
unsigned char *outbuf;
int outlen, templen, inlen;
inlen = [secretText length];
unsigned char evp_key[EVP_MAX_KEY_LENGTH] = {"\0"};
int cipherMaxIVLength = EVP_MAX_IV_LENGTH;
EVP_CIPHER_CTX cCtx;
const EVP_CIPHER *cipher = EVP_bf_cbc();
cipherMaxIVLength = EVP_CIPHER_iv_length( cipher );
unsigned char iv[cipherMaxIVLength];
EVP_BytesToKey(cipher, EVP_md5(), NULL, [symmetricKey bytes], [symmetricKey length], 1, evp_key, iv);
NSData *initVector = [NSData dataWithBytes:iv length:cipherMaxIVLength];
EVP_CIPHER_CTX_init(&cCtx);
if (!EVP_EncryptInit_ex(&cCtx, cipher, NULL, evp_key, iv)) {
EVP_CIPHER_CTX_cleanup(&cCtx);
return nil;
}
int ctx_CipherKeyLength = EVP_CIPHER_CTX_key_length( &cCtx );
EVP_CIPHER_CTX_set_key_length(&cCtx, ctx_CipherKeyLength);
outbuf = (unsigned char *)calloc(inlen + EVP_CIPHER_CTX_block_size(&cCtx), sizeof(unsigned char));
if (!EVP_EncryptUpdate(&cCtx, outbuf, &outlen, input, inlen)){
EVP_CIPHER_CTX_cleanup(&cCtx);
return nil;
}
if (!EVP_EncryptFinal(&cCtx, outbuf + outlen, &templen)){
EVP_CIPHER_CTX_cleanup(&cCtx);
return nil;
}
outlen += templen;
EVP_CIPHER_CTX_cleanup(&cCtx);
NSData *cipherText = [NSData dataWithBytes:outbuf length:outlen];
NSString *base64String = [cipherText encodeBase64WithNewlines:NO];
NSString *iv = [initVector encodeBase64WithNewlines:NO];
然后将 base64String 和 iv 发布到 PHP 以尝试对其进行解码:
<?php
import_request_variables( "p", "p_" );
if( $p_data != "" && $p_iv != "" )
{
$encodedData = base64_decode( $p_data, true );
$iv = base64_decode( $p_iv, true );
$td = mcrypt_module_open( MCRYPT_BLOWFISH, '', MCRYPT_MODE_CBC, '' );
$keySize = mcrypt_enc_get_key_size( $td );
$key = substr( md5( "ThisIsMyKey" ), 0, $keySize );
$decodedData = mcrypt_decrypt(MCRYPT_BLOWFISH, $key, $encodedData, MCRYPT_MODE_CBC, $iv );
mcrypt_module_close( $td );
echo "decoded: " . $decodedData;
}
?>
decodedData 总是乱码。
我已经尝试反转该过程,将编码输出从 PHP 发送到 Cocoa,但 EVP_DecryptFinal() 失败,这让我相信某处存在 NULL 填充问题。我已经阅读并重新阅读了 PHP 和 OpenSSL 文档,但现在它们都模糊不清了,我没有想法可以尝试。