Посмотрим.PKCS # 7 описан в RFC 5652 (Синтаксис криптографических сообщений).
Сама схема заполнения приведена в разделе 6.3.Процесс шифрования контента .По сути, это говорит: добавьте столько байтов, сколько необходимо для заполнения заданного размера блока (но не менее одного), и каждый из них должен иметь длину заполнения в качестве значения.
Таким образом, глядя на последний расшифрованный байт, мызнаю, сколько байтов скинуть.(Можно также проверить, что все они имеют одинаковое значение.)
Теперь я мог бы дать вам пару функций PHP, чтобы сделать это, но мой PHP немного ржавый.Так что либо делайте это самостоятельно (затем смело редактируйте мой ответ, чтобы добавить его), либо посмотрите примечания, внесенные пользователем в документацию mcrypt - некоторые из них посвящены заполнению и предоставлениюреализация заполнения PKCS # 7.
Итак, давайте посмотрим на первую заметку там в деталях:
<?php
function encrypt($str, $key)
{
$block = mcrypt_get_block_size('des', 'ecb');
Получается размер блокаИспользуемый алгоритм.В вашем случае вы бы использовали aes
или rijndael_128
вместо des
, я полагаю (я не проверял это).(Вместо этого вы можете просто взять 16
здесь для AES вместо вызова функции.)
$pad = $block - (strlen($str) % $block);
Это вычисляет размер заполнения.strlen($str)
- длина ваших данных (в байтах), % $block
- остаток по модулю $block
, то есть количество байтов данных в последнем блоке.$block - ...
, таким образом, дает количество байтов, необходимое для заполнения этого последнего блока (теперь это число от 1
до $block
включительно).
$str .= str_repeat(chr($pad), $pad);
str_repeat
создает строку, состоящую из повторения одной и той же строки, здесь повторение символа , заданного $pad
, $pad
раз, т.е. строка длиной $pad
, заполненная $pad
,$str .= ...
добавляет эту строку дополнения к исходным данным.
return mcrypt_encrypt(MCRYPT_DES, $key, $str, MCRYPT_MODE_ECB);
Вот само шифрование.Используйте MCRYPT_RIJNDAEL_128
вместо MCRYPT_DES
.
}
Теперь другое направление:
function decrypt($str, $key)
{
$str = mcrypt_decrypt(MCRYPT_DES, $key, $str, MCRYPT_MODE_ECB);
Расшифровка.(Вы, конечно, изменили бы алгоритм, как указано выше).$ str теперь является расшифрованной строкой, включая отступы.
$block = mcrypt_get_block_size('des', 'ecb');
Это снова размер блока.(См. Выше.)
$pad = ord($str[($len = strlen($str)) - 1]);
Это выглядит немного странно.Лучше напишите это в несколько шагов:
$len = strlen($str);
$pad = ord($str[$len-1]);
$len
теперь длина добавленной строки, а $str[$len - 1]
- последний символ этой строки.ord
преобразует это число.Таким образом, $pad
- это число, которое мы ранее использовали в качестве значения заполнения для заполнения, и это длина заполнения.
return substr($str, 0, strlen($str) - $pad);
Итак, теперь мы отрезаем последние $pad
байтов из строки.(Вместо strlen($str)
мы могли бы также написать $len
здесь: substr($str, 0, $len - $pad)
.).
}
?>
Обратите внимание, что вместо использования substr($str, $len - $pad)
можно также написать substr($str, -$pad)
в качестве *Функция 1087 * в PHP имеет специальную обработку для отрицательных операндов / аргументов, чтобы отсчитывать от конца строки.(Я не знаю, является ли это более или менее эффективным, чем сначала получить длину и вычислить индекс вручную.)
Как было сказано выше и отмечено в комментарии Россумом, вместо простого удаления отступовкак сделано здесь, вы должны проверить, что это правильно - то есть посмотрите на substr($str, $len - $pad)
и убедитесь, что все его байты chr($pad)
.Это служит небольшой проверкой на предмет коррупции (хотя эта проверка более эффективна, если вы используете режим цепочки вместо ECB, и не является заменой для реального MAC).
(И все же, скажитеВашему клиенту они должны подумать о переходе на более безопасный режим, чем ECB.)