我試圖解決的情況解碼:在我的可可應用程序,我需要一個字符串對稱密碼加密,張貼到PHP,並讓該腳本解碼數據。該過程需要反向工作以返回答案(PHP編碼,Cocoa解碼)。對數據進行加密,在PHP(反之亦然)
我失去了一些東西,因爲即使我可以同時獲得密鑰和初始化向量(IV)是在PHP和可可相同,當一個應用程序發送它的編碼數據提供給其他解碼永遠不會奏效。兩者都可以很好地對他們自己的數據進行編碼/解碼(驗證以確保手邊沒有一些PEBKAC問題)。我懷疑某處存在填充問題,我只是沒有看到它。
我的可可應用編碼使用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發送編碼輸出到可可,但EVP_DecryptFinal()失敗,這是什麼導致我相信有一個NULL填充問題的地方。我已經閱讀並重新閱讀了PHP和OpenSSL文檔,但現在它們都變得模糊起來,並且我沒有想法嘗試。
[OpenSSL 1.1.0c更改了摘要算法](http://stackoverflow.com/q/39637388/608639)在某些內部組件中使用。以前使用MD5,1.1.0切換到SHA256。請注意,這些更改不會影響`EVP_BytesToKey`和像`openssl enc`這樣的命令。 – jww 2017-01-26 16:24:14