У меня есть приложение iOS, которое шифрует данные с использованием AES 128 CBC. Я могу расшифровать эти данные в приложении в объекте-c, так что, по крайней мере, мне говорят, что шифрование работает правильно в этом контексте (Common Crypto). Проблема в том, что мне нужно отправить эти зашифрованные данные на сервер и расшифровать его через PHP. Вот где я терплю неудачу.Ошибка дешифрования AES 128
Я вручную сделал шифрование в командной строке с помощью openssl. Используя этот вывод и вернув его в эту функцию php, я могу правильно расшифровать, поэтому я знаю, что функция php работает правильно, по крайней мере, относительно openssl. Итак, проблема заключается в том, как заставить Objective-C выводить зашифрованный текст так же, как и openssl (или как заставить php расшифровывать зашифрованный текст из Common Crypto). Другими словами, каждая из этих функций «работает» в своем собственном контексте.
<?php
function jsonEncode ($result, $message) {
$arr = array('result' => $result, 'message' => $message);
echo json_encode($arr);
}
//$ciphertext = base64_decode($_POST['ciphertext']);
//$iv = $_POST['iv'];
// overriding the http post values with values copied in from console output for testing
$ciphertext = base64_decode('dwb7MWCQUUiVuJLzL2EzYm0NcodwORP47qPhLzaolAk=');
// openssl on the command line yields ciphertext of
// 'gRiOXseXTjhpPCiiHgnaQQoal3a9E87Gx3FVpZPtR1I=' which decrypts successfully
$iv = 'hkPDfznq1t1UpKrW';
$key = 'T8ZvJba0HHsmiVSD';
//$plaintext = openssl_decrypt($ciphertext, 'aes-128-cbc', $key, false, $iv);
//jsonEncode('success', $plaintext);
// this is the line that fails
$plaintext = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $ciphertext, MCRYPT_MODE_CBC, $iv);
//$padding = ord($plaintext[strlen($plaintext) - 1]);
//jsonEncode('success', substr($plaintext, 0, -$padding));
jsonEncode('success', $plaintext);
?>
EDIT: на основе очень полезный комментарий от @Zaph ниже, я переписал свою функцию шифрования в Objective-C, чтобы сделать отступы вручную. Я думаю, что это правильно. Однако, когда функция php возвращается, функция mcrypt_decrypt
вычисляет значение false. Вот новая функция Objective C:
- (NSData *)AES128EncryptWithKey:(NSString *)key iv:(NSString *)iv
{
char keyPtr[kCCKeySizeAES128+1];
bzero(keyPtr, sizeof(keyPtr));
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
char ivPtr[kCCBlockSizeAES128 + 1];
bzero(ivPtr, sizeof(ivPtr));
if (iv) {
[iv getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSUTF8StringEncoding];
}
NSUInteger dataLength = [self length];
int diff = kCCKeySizeAES128 - (dataLength % kCCKeySizeAES128);
int newSize = 0;
if(diff > 0) {
newSize = (int)(dataLength + diff);
}
// manually add padding to the end of the data array
char dataPtr[newSize];
memcpy(dataPtr, [self bytes], [self length]);
for(int i = 0; i < diff; i++) {
dataPtr[i + dataLength] = diff;
}
dataPtr[newSize] = '\0';
size_t bufferSize = newSize + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
// print out the padded array for verification
NSLog(@"diff: %d new size: %d", diff, newSize);
for (int i=0; i<newSize; i++)
printf("0x%x ", dataPtr[i]);
printf("\n");
size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,
kCCAlgorithmAES128,
0x0000, //No padding
keyPtr,
kCCKeySizeAES128,
ivPtr,
dataPtr,
sizeof(dataPtr),
buffer,
bufferSize,
&numBytesEncrypted);
if(cryptStatus == kCCSuccess) {
return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
}
return nil;
}
Objective C консоли Выход:
diff: 12 new size: 32
0x65 0x6e 0x63 0x72 0x79 0x70 0x74 0x69 0x6f 0x6e 0x20 0x69 0x73 0x20 0x74 0x72 0x69 0x63 0x6b 0x79 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc
encrypted text: dwb7MWCQUUiVuJLzL2EzYm0NcodwORP47qPhLzaolAk=
Простой текст "шифрование сложно.
любая причина, по которой вы делаете свое собственное шифрование? Вы могли бы просто использовать ssl, который дал бы вам шифрование для «бесплатного». –
Я не использую свое собственное шифрование. Я использую CommonCrypto из библиотеки Apple Developer. – Alex
@MarcB Common Crypto - встроенные криптографические библиотеки Apple для iOS. OpenSSL не поставляется для iOS, поэтому он не свободен в том смысле, что нужно получить источник и скомпилировать его, что нелегко. – zaph