Intereting Posts
Изменение заголовков Grafana (Access-Control-Allow-Origin) Symfony2 – класс не найден Как получить токен доступа без вмешательства пользователя для известной учетной записи с помощью API Google Youtube v3? Почему сеанс PHP удален при перезагрузке страницы? Должен ли я использовать несколько классов для игры? раунд в PHP показывает научную нотацию вместо полного числа Nginx заменит REMOTE_ADDR на X-Forwarded-For Обработка больших наборов данных через AJAX не приносит никаких преимуществ по скорости PHP проверяет, превышает ли отметка времени более 24 часов как фильтровать, скрывая / показывая divs с динамическими атрибутами? Code Logic для предотвращения столкновения между двумя оговорками изменение log_errors_max_len не влияет SQLSTATE : Недопустимый номер параметра: количество связанных переменных не совпадает с числом токенов в строке 102 Laravel 5 isDirty () всегда возвращает false Оператор логического выражения оператора case в Java – против JS или PHP

RNCryptor AES256 соответствует PHP MCRYPT_RIJNDAEL_256

PHP API, который я вызываю из моего приложения iOS, требует, чтобы полезная нагрузка была зашифрована определенным образом. У меня возникают проблемы, повторяющие этот подход в Objective-C с помощью RNCryptor.

Вот код PHP, используемый для шифрования строки:

function encrypt($string) { $key = 'some-random-key'; return base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, md5($key), $string, MCRYPT_MODE_CBC, md5(md5($key)))); } 

И это, как я пытаюсь добиться того же результата шифрования в Objective-C:

 + (NSData*)encryptData:(NSData*)sourceData { NSString *keyString = @"some-random-key"; NSData *key = [[keyString MD5String] dataUsingEncoding:NSUTF8StringEncoding]; NSData *iv = [[[keyString MD5String] MD5String] dataUsingEncoding:NSUTF8StringEncoding]; NSMutableData *encryptedData = [NSMutableData data]; RNCryptorEngine *cryptor = [[RNCryptorEngine alloc] initWithOperation:kCCEncrypt settings:kRNCryptorAES256Settings key:key IV:iv error:nil]; [encryptedData appendData:[cryptor addData:sourceData error:nil]]; [encryptedData appendData:[cryptor finishWithError:nil]]; return encryptedData; } 

Но результаты двух функций никогда не совпадают. Например, для той же однословной строки код PHP возвращает J39gRcuBEaqMIPP1VlizdA8tRjmyAB6za4zG5wcOB/8= , в то время как в Objective-C (после запуска base64EncodedStringWithOptions: в результате NSData) я получаю 1FGpZpVm2p4z3BBY6KW2fw== .

Есть ли что-то, что мне нужно для дальнейшей настройки в настройках RNCryptor, чтобы заставить его работать?

ОБНОВИТЬ

Я напрямую играл вокруг родной инфраструктуры iOS CommonCrypto, без использования стороннего RNCryptor lib. Я все равно получаю тот же результат, что и в RNCryptor. Я даже пытался реализовать AES128 в обоих моих объектных-С и PHP-фрагментах, но даже это не привело к тому, что результаты из двух сред совпали …

ОБНОВЛЕНИЕ 2

Метод MD5String который я использую, является категорией в NSString и определяется следующим образом:

 - (NSString *)MD5String { const char *cstr = [self UTF8String]; unsigned char result[16]; CC_MD5(cstr, strlen(cstr), result); return [[NSString stringWithFormat: @"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7], result[8], result[9], result[10], result[11], result[12], result[13], result[14], result[15] ] lowercaseString]; } 

Хотя в большинстве ответов основное внимание уделяется хеш-файлу MD5, наиболее вероятным вызовом является тот факт, что MCRYPT_RIJNDAEL_256 не является AES. Он не определяет размер ключа 256, а размер блока – 256, тогда как AES всегда имеет размер блока 128 бит. Что касается других параметров, распечатайте их значения в шестнадцатеричном порядке перед процедурой шифрования с обеих сторон, чтобы узнать их значения.

Я понимаю, что опаздываю на вечеринку, и вы, наверное, уже переехали. Но я хочу отметить, что теперь есть полный PHP-порт RNCryptor, который является поточным потоком, совместимым с реализацией Objective-C. Я сам внес свой вклад прошлым летом, и в настоящее время я поддерживаю его. 🙂

Поэтому теперь довольно легко шифровать с помощью RNCryptor PHP и расшифровывать с помощью RNCryptor Objective-C или наоборот. Ознакомьтесь с основным проектом RNCryptor для получения подробной информации и списка подпроектов.

Необычно возвращать md5 как hex-ascii в отличие от языков сценариев, даже php предоставляет двоичный выходной параметр.

Есть несколько n стандартных вещей о php mcrypt_encrypt :

  1. Заполнение ключа с помощью \ 0, если он меньше требуемого размера ключа.
  2. Данные будут дополнены символами \ 0 до кратного размера блока, обычно используется дополнение, такое как pkcs7 .
  3. Не указано, как обрабатывается iv, который не является размером блока, можно предположить, что он также дополняется символами конца \ 0.

Из них iv будет правильной длиной из-за установки hex-ascii из метода md5 . Но это оставляет длину данных и заполнение, которое является нестандартным.

Ключ будет 32 байта, поэтому он будет дополнен 32 \ 0 символами в php. Это вызывает вопрос об использовании AES256 с 128-битным ключом.

Из основного CommonCrypto "CommonCryptor.h":

keyLength: Длина ключевого материала. Должна быть подходящей для выбранной операции и алгоритма.

Длина ключа неверна.

Дела, которые необходимо сделать:
1. Обрабатывать длину и длину данных
2. Обработать длину ключа

Для получения дополнительной информации, пожалуйста, укажите образцы данных, которые вы используете, и hex-ascii out, помещенный в mcrypt_encrypt до кодировки base64.

Для справки см .:
mcrypt-encrypt.php и md5.php

Замечание Зафа, что

Данные будут дополнены символами \ 0 до кратного размера блока

поставил меня на путь и помог мне разобраться в части проблемы.

По сути, в mcrypt PHP используется только \0 padding для данных, в то время как CommonCryptor от Apple позволяет вам выбирать между дополнением kCCOptionPKCS7Padding ( kCCOptionPKCS7Padding ) или без прокладки. Это была одна из причин, по которой я никогда не смог получить данные: она всегда была различной по-разному, прежде чем она собиралась зашифровать.

Решение для этого состоит в том, чтобы либо заставить PHP выполнять PKCS7 заполнение данных перед запуском mcrypt ( mcrypt решение ), либо сделать Objective-C выполненным положением PHP-style \0 и обязательно удалить kCCOptionPKCS7Padding (передать опции NULL в CCCrypt):

 NSMutableData *dataToEncrypt = [sourceData mutableCopy]; NSUInteger dataLength = [dataToEncrypt length]; // See how much padding is required NSUInteger padding = kCCBlockSizeAES128 - (dataLength % kCCBlockSizeAES128); // Add that many \0's (there could be a more efficient way to do this) for (int i=0; i<padding; i++) [dataToEncrypt appendData:[@"\0" dataUsingEncoding:NSASCIIStringEncoding]]; // Recalculate the data length dataLength = dataToEncrypt.length; 

Я закончил работу с RNCryptor и работал с родным CommonCryptor API напрямую, поэтому конечный результат выглядел примерно так (метод encryptedBase64String здесь является категорией в NSString в моем приложении, потому что мне только нужно зашифровать строки таким образом, а также отметить константа kHSEncryptionKey представляющая строку ключа свободной формы):

 - (NSString*)encryptedBase64String { // Prepare the data NSMutableData *sourceData = [[self dataUsingEncoding:NSUTF8StringEncoding] mutableCopy]; // Process the key NSString *key = [[kHSEncryptionKey MD5String] substringWithRange:NSMakeRange(0, 16)]; char keyPtr[kCCKeySizeAES128 + 1]; bzero(keyPtr, sizeof(keyPtr)); [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding]; // Process the iv NSString *iv = [[[kHSEncryptionKey MD5String] MD5String] substringWithRange:NSMakeRange(0, 16)]; char ivPtr[kCCKeySizeAES128 + 1]; bzero(ivPtr, sizeof(ivPtr)); [iv getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSUTF8StringEncoding]; // Pad the data, PHP style NSUInteger dataLength = [sourceData length]; NSUInteger padding = kCCBlockSizeAES128 - (dataLength % kCCBlockSizeAES128); for (int i=0; i<padding; i++) [sourceData appendData:[@"\0" dataUsingEncoding:NSASCIIStringEncoding]]; dataLength = sourceData.length; // Buffer for the resulting data size_t bufferSize = dataLength + kCCBlockSizeAES128; void* buffer = malloc(bufferSize); // Run the encryption size_t numBytesEncrypted = 0; CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, NULL, keyPtr, kCCKeySizeAES128, ivPtr, sourceData.bytes, dataLength, /* input */ buffer, bufferSize, /* output */ &numBytesEncrypted); if (cryptStatus == kCCSuccess) { NSData *encyptedData = [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted]; return [encyptedData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength]; } free(buffer); return nil; }