У меня есть время выяснить, как расшифровать строку, зашифрованную с помощью NSData + AESCrypt.m (поясняется здесь )
Я смотрел на несколько других потоков, но мне нужно только iDevice для отправки строки в файл PHP, зашифрованного, а затем он расшифровывается внутри PHP (где он хранится в базе данных).
Этот код:
NSString *encryptedString = [@"Hello" AES256EncryptWithKey:@"a16byteslongkey!"]; NSLog(@"The strign encrypted : %@",encryptedString);
Возвращает строку, зашифрованную: 7opqbb7sEVNoXplyQv / X8g ==
И вот мой PHP-код для расшифровки:
function decrypt_data($data, $key) { return mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key,$data,MCRYPT_MODE_ECB); } function unpadPKCS7($data, $blockSize) { $length = strlen ( $data ); if ($length > 0) { $first = substr ( $data, - 1 ); if (ord ( $first ) <= $blockSize) { for($i = $length - 2; $i > 0; $i --) if (ord ( $data [$i] != $first )) break; return substr ( $data, 0, $i ); } } return $data; } function decrypt_string($string) { $string = unpadPKCS7($string,128); $string = decrypt_data($string,"a16byteslongkey!"); return $string; } die('<br>Basic :'.decrypt_string('7opqbb7sEVNoXplyQv/X8g=='));
ОБНОВИТЬ:
Выполнял дешифрование MD5 и много экспериментировал, но еще далек от достижения полезных результатов. Это то, что я получил до сих пор:
Original string : Hello AES256Encrypt result : 7opqbb7sEVNoXplyQv/X8 base64_decode Decrypted: îŠjm¾ìSh^™rBÿ× mcrypt_rijndael_128 : Õ¯Öå«Ž(ás2''u) mcrypt_rijndael_128 & hex2bin : UÃ)ı+úy´e
К сожалению, независимо от того, как я наклоняюсь и скручиваю это, я просто становлюсь бред. Может ли кто-нибудь увидеть, что я делаю неправильно?
Отказ от ответственности: у меня нет опыта разработки iPhone.
Короткий ответ – что тк. сказал. Что-то ужасно неправильно с AES256EncryptWithKey
:
Будучи AES256, вы ожидаете, что потребуется 32-байтовый ключ, а не 16-байтовый ключ. Но ОК, скажите, что он укладывает более короткие ключи с нулевыми байтами, чтобы сделать их 32 байтами. Это может объяснить, почему ваш 16-байтовый ключ заполняется 16 символами.
Но когда дело доходит до фактического действия шифрования, оно использует AES 128, но с 32-байтовым ключом. Скажи что?
Преобразование tc.'s Python в PHP:
$base64encoded_ciphertext = '7opqbb7sEVNoXplyQv/X8g=='; $key = 'a16byteslongkey!'; $padded_key = $key . str_repeat(chr(0x00), 16); // Argh! $result = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $padded_key, base64_decode($base64encoded_ciphertext), 'ecb'); // Yetch - $result ends up being padded with 0x0b's (vertical tab). var_dump(rtrim($result, chr(0x0b)));
Результат:
string (5) "Hello"
~~
Редактировать: Этот пост от Henno содержит некоторые важные сведения.
~~
Провели некоторые дополнительные исследования. Нулевой пробел на вашем ключе, вероятно, потому, что для AES256 требуется 32-байтовый ключ. Заполнение 0x0B открытым текстом – благодаря PKCS7 . PKCS7 – это схема дополнений, в которой байт, используемый для заполнения, равен по значению количеству добавленных байтов. В этом примере в конец «Hello» добавлено 11 байтов, которые превратили ваш 5-байтовый вход в 16-байтовый блок для AES. 11 = 0x0B.
Таким образом, приведенный выше код не будет работать, если открытый текст не равен length = 5. Вместо этого попробуйте следующее:
$pad_char = ord(substr($result, -1)); $result_without_padding = substr($result, 0, strlen($result) - $pad_char);
Зашифрованная строка выглядит так, как будто она закодирована в base64. Попробуйте расшифровать его, прежде чем расшифровать его.
Во-первых, код Objective-C, который вы используете, довольно ужасен:
Избегайте его любой ценой. Это не безопасно.
Он может быть «расшифрован» в Python с чем-то вроде этого:
>>> import Crypto.Cipher.AES >>> import base64 >>> Crypto.Cipher.AES.new('a16byteslongkey!'+'\0'*16).decrypt(base64.b64decode('7opqbb7sEVNoXplyQv/X8g==')) 'Hello\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b'
см. мой пост здесь: PHP iOS AES Encryption
Я просто прошел через этот проект. Я использовал библиотеку, на которую вы ссылались, в «также рассмотренной …»
Вот пример кода для расшифровки с помощью php:
$iv2 = ''; for($i=0;$i<16;$i++){ $iv2 .= "\0"; } $plain_text_CBC = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $encrypted_text, MCRYPT_MODE_CBC, $iv2); var_dump($plain_text_CBC);
Убедитесь, что ваши ключи оба 256-битные (32 символа, у меня еще не было проблем с кодировкой, но если вы это сделаете, помните, что вы шифруете байты, а не символы). Обратите внимание: 128 в MCRYPT_RIJNDAEL_128 – это размер блока, а не размер ключа, а в методе AES256DecryptWithKey 256 – это ссылка на размер ключа, а размер блока – 128. AES256DecryptWithKey работает в режиме CBC, но имеет нулевой вектор инициализации ( IV).
CBC означает, что каждый блок зависит от последнего блока, и поэтому он использует предварительно установленный, обычно случайный, «блок -1», называемый IV
ECB означает, что каждый блок зашифрован таким же образом, поэтому он показывает, когда два блока в одном сообщении одинаковы. В упомянутой библиотеке не используется, поэтому я упомянул об этом просто для контраста.
Использование нуля iv (0000000000000000 в байтах) считается небезопасным, но оно предоставляет вам дополнительную защиту (но все равно можно было бы сказать, были ли каждый 16-й символ вашего обычного текста одинаковым каждый раз). Чтобы исправить это, вам нужно будет создать переменную NSData * iv для IV и изменить аргумент CCcrypt NSData + AESCrypt.m, чтобы добавить [iv bytes] для параметра iv (я еще не тестировал этот код), и вы бы необходимо сохранить этот iv и передать его на php вместе с вами. Но сначала я бы проверил и все работаю с нулевым iv.