Intereting Posts

Получить IV из заголовка RNCryptor AES 256 в PHP

Используя последний источник RNCryptor и попытайтесь отправить зашифрованные данные в PHP-скрипт.

RNCryptor передает IV в секцию заголовка, которая добавляется к фактическим зашифрованным данным.

- (NSData *)header { uint8_t header[2] = {kRNCryptorFileVersion, self.options}; NSMutableData *headerData = [NSMutableData dataWithBytes:header length:sizeof(header)]; if (self.options & kRNCryptorOptionHasPassword) { [headerData appendData:self.encryptionSalt]; // 8 bytes [headerData appendData:self.HMACSalt]; // 8 bytes } [headerData appendData:self.IV]; // BlockSizeAES128 return headerData; } 

Я новичок в работе с двоичными данными в PHP, правильно ли я использую следующую функцию распаковки?

 <? $baseEncodedString = "..."; $data = mb_convert_encoding($baseEncodedString, "UTF-8", "BASE64" ); $array = unpack("Cversion/Coptions/C8salt/C8hmac/C16iv/C*aes", $data); print_r($array); ?> 

ПРИМЕЧАНИЕ. Зашифрованные данные Base64 кодируются из какао перед передачей.

Вышеупомянутый PHP-скрипт возвращает данные, такие как …

Массив ([версия] => 1 [опции] => 1 [соль1] => 109 [соль2] => 195 [соль3] => 185 [соль4] => 71 [соль5] => 130 [соль6] => 209 [соль7] => 230 [соль8] => 25 [hmac1] => 8 [hmac2] => 152 [hmac3] => 188 [hmac4] => 135 [hmac5] => 117 [hmac6] => 169 [hmac7 ] => 25 [hmac8] => 228 [iv1] => 43 [iv2] => 220 [iv3] => 80 [iv4] => 102 [iv5] => 142 [iv6] => 144 [iv7] = > 172 [iv8] => 104 [iv9] => 216 [iv10] => 45 [iv11] => 155 [iv12] => 117 [iv13] => 188 [iv14] => 67 [iv15] => 24 [iv16] => 191 [aes1] => 122 [aes2] => 227 [aes3] => 45 [aes4] => 194 [aes5] => 57 [aes6] => 123 [aes7] => 28 [aes8 ] => 130 [aes9] => 110 [aes10] => 122 [aes11] => 97 [aes12] => 118 [aes13] => 214 [aes14] => 117 [aes15] => 56 [aes16] = > 168 [aes17] => 54 [aes18] => 198 [aes19] => 113 [aes20] => 120 [aes21] => 138 [aes22] => 67 [aes23] => 223 [aes24] => 200 [aes25] => 11 [aes26] => 109 [aes27] => 177 [aes28] => 167 [aes29] => 103 [aes30] => 139 [aes31] => 243 [aes32] => 199 [aes33 ] => 214 [aes34] => 214 [aes35] => 241 [aes36] = > 199 [aes37] => 173 [aes38] => 219 [aes39] => 71 [aes40] => 97 [aes41] => 32 [aes42] => 27 [aes43] => 248 [aes44] ​​=> 175 [aes45] => 203 [aes46] => 123 [aes47] => 21)

Как я могу использовать это в функциях PHP MCrypt?

Благодарю.


РЕДАКТИРОВАТЬ

В ответ на ответ drew010 я обновил свой PHP-скрипт до следующего …

 <? function pbkdf2($algorithm, $password, $salt, $count, $key_length, $raw_output = false) { $algorithm = strtolower($algorithm); if(!in_array($algorithm, hash_algos(), true)) die('PBKDF2 ERROR: Invalid hash algorithm.'); if($count <= 0 || $key_length <= 0) die('PBKDF2 ERROR: Invalid parameters.'); $hash_length = strlen(hash($algorithm, "", true)); $block_count = ceil($key_length / $hash_length); $output = ""; for($i = 1; $i <= $block_count; $i++) { // $i encoded as 4 bytes, big endian. $last = $salt . pack("N", $i); // first iteration $last = $xorsum = hash_hmac($algorithm, $last, $password, true); // perform the other $count - 1 iterations for ($j = 1; $j < $count; $j++) { $xorsum ^= ($last = hash_hmac($algorithm, $last, $password, true)); } $output .= $xorsum; } if($raw_output) return substr($output, 0, $key_length); else return bin2hex(substr($output, 0, $key_length)); } $base = $_GET['base']; $data = mb_convert_encoding($base, "UTF-8", "BASE64" ); //$data = base64_decode($base); $header = array(); $header['ver'] = substr($data, 0, 1); $header['options'] = substr($data, 1, 1); $header['salt'] = substr($data, 2, 8); $header['hmac'] = substr($data, 10, 8); $header['iv'] = substr($data, 18, 16); $data = substr($data, 34); $td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, ''); mcrypt_generic_init($td, pbkdf2('SHA256', 'password', $header['salt'], 10000, 16), $header['iv']); //$decrypted = mcrypt_decrypt('rijndael-256','password',$data,'',$header['iv']); $decrypted = mdecrypt_generic($td, $data); echo $decrypted; ?> 

Как бы то ни было, я все еще получаю скремблированный текст.

U¸|uÀÆ & bŸ8: f`ôShŽºÃ ~: ¾ÉöÁß = Ç®nqäà € • Æ <ò

Я снова посмотрел на RNCryptor и использовал следующие значения для скрипта PHP

 static const RNCryptorSettings kRNCryptorAES256Settings = { .algorithm = kCCAlgorithmAES128, .blockSize = kCCBlockSizeAES128, .IVSize = kCCBlockSizeAES128, .options = kCCOptionPKCS7Padding, .HMACAlgorithm = kCCHmacAlgSHA256, .HMACLength = CC_SHA256_DIGEST_LENGTH, .keySettings = { .keySize = kCCKeySizeAES256, .saltSize = 8, .PBKDFAlgorithm = kCCPBKDF2, .PRF = kCCPRFHmacAlgSHA1, .rounds = 10000 }, .HMACKeySettings = { .keySize = kCCKeySizeAES256, .saltSize = 8, .PBKDFAlgorithm = kCCPBKDF2, .PRF = kCCPRFHmacAlgSHA1, .rounds = 10000 } }; 

Эта функция, я считаю, дает ключ?

 + (NSData *)keyForPassword:(NSString *)password salt:(NSData *)salt settings:(RNCryptorKeyDerivationSettings)keySettings { NSMutableData *derivedKey = [NSMutableData dataWithLength:keySettings.keySize]; int result = CCKeyDerivationPBKDF(keySettings.PBKDFAlgorithm, // algorithm password.UTF8String, // password password.length, // passwordLength salt.bytes, // salt salt.length, // saltLen keySettings.PRF, // PRF keySettings.rounds, // rounds derivedKey.mutableBytes, // derivedKey derivedKey.length); // derivedKeyLen // Do not log password here // TODO: Is is safe to assert here? We read salt from a file (but salt.length is internal). NSAssert(result == kCCSuccess, @"Unable to create AES key for password: %d", result); return derivedKey; } 

Еще раз спасибо.

Правильно ли MCRYPT_RIJNDAEL_128? Несмотря на то, что настройки RNCryptor предполагают использование 256, фактически алгоритм равен 128, а размер IV относится к размеру блока 128. Я где-то читал, чтобы заставить PHP использовать 16-байтный IV, вы должны использовать MCRYPT_RIJNDAEL_128, а затем 256-битный файл – 32-байтовый ключ.

Solutions Collecting From Web of "Получить IV из заголовка RNCryptor AES 256 в PHP"

Это работает для меня с последним RNCryptor в iOS

$b64_data : зашифрованные данные с кодировкой base64
$pwd : пароль

 // back to binary $bin_data = mb_convert_encoding($b64_data, "UTF-8", "BASE64"); // extract salt $salt = substr($bin_data, 2, 8); // extract HMAC salt $hmac_salt = substr($bin_data, 10, 8); // extract IV $iv = substr($bin_data, 18, 16); // extract data $data = substr($bin_data, 34, strlen($bin_data) - 34 - 32); // extract HMAC $hmac = substr($bin_data, strlen($bin_data) - 32); // make HMAC key $hmac_key = $this->pbkdf2('SHA1', $password, $hmac_salt, 10000, 32, true); // make HMAC hash $hmac_hash = hash_hmac('sha256', $data , $hmac_key, true); // check if HMAC hash matches HMAC if($hmac_hash != $hmac) return false; // make data key $key = $this->pbkdf2('SHA1', $password, $salt, 10000, 32, true); // decrypt $ret = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC, $iv); return trim(preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x80-\xFF]/u', '', $ret)); 

pbkdf2 такой же, как в вопросе выше, от https://defuse.ca/php-pbkdf2.htm .

Для этого вам не нужно использовать распаковку.

После того, как вы получите полную кодировку base64, декодируйте ее, и теперь вы должны иметь двоичную строку с IV в начале строки.

Затем вы можете использовать substr() для захвата каждой части, требуемой вами из данных.

Например:

 $base = $_GET['base']; $data = base64_decode($base); $iv = substr($data, 0, 32); // get 32 byte IV $data = substr($data, 32); // set data to begin after the IV now 

Если у вас есть другие поля, добавленные к зашифрованному тексту, обязательно сделайте то же, что и выше, с другими данными в правильной последовательности.

Когда у вас есть эти данные, вы можете передать $data в mcrypt вместе с IV и вашим ключом.

Правильно ли MCRYPT_RIJNDAEL_128? Несмотря на то, что настройки RNCryptor предполагают использование 256, фактически алгоритм равен 128, а размер IV относится к размеру блока 128. Я где-то читал, чтобы заставить PHP использовать 16-байтный IV, вы должны использовать MCRYPT_RIJNDAEL_128, а затем 256-битный файл – 32-байтовый ключ.

«128» в MCRYPT_RIJNDAEL_128 относится к размеру блока, а не к размеру ключа. Алгоритм Rijndael может обрабатывать несколько размеров блоков, но AES может обрабатывать только 128-битные блоки. Это не зависит от размера ключа. CBC IV всегда должен быть размером блока, который снова всегда равен 16 байтам в AES. (Rijndael и AES очень похожи, но не идентичны. Rijndael более гибкий, чем AES).

В вашей функции pbkdf2() вы должны передать длину ключа 32 байта (256 бит), а не 16 байт. Я считаю, что PHP mcrypt-модуль автоматически переключится на 256-битный AES, если будет передан 256-битный ключ (на основе комментариев о понимании PHP AES Encryption , я не особо знаком с mcrypt). Я предполагаю, что вы правильно выполняете PBKDF2; Я не изучил ваш код там.

Обратите внимание, что RNCryptor добавляет 32-байтовый HMAC в конце. Я считаю, что ваш текущий код попытается расшифровать его, что приведет к 32 байтам мусора в конце. Как правило, вы должны отключить этот HMAC и проверить его, чтобы убедиться, что данные не были изменены при переходе и что пароль верен.