私が解決しようとしている状況: 私の Cocoa アプリでは、対称暗号で文字列を暗号化し、それを PHP に POST し、そのスクリプトでデータをデコードする必要があります。回答を返すには、このプロセスを逆に実行する必要があります (PHP エンコード、Cocoa デコード)。
PHP と Cocoa の両方でキーと初期化ベクトル (iv) の両方を同じにすることはできますが、一方のアプリがエンコードされたデータを他方に送信すると、デコードが機能しないため、何かが欠けています。どちらも独自のデータのエンコード/デコードに問題なく機能します (手元に 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 に POST されます。
<?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 のドキュメントを読んで読み直しましたが、今ではすべてがぼやけていて、試してみるアイデアがありません。