Безопасный non-tamperable компонент URL в Perl с помощью симметричного шифрования?

Хорошо, у меня, вероятно, просто есть плохое в понедельник, но у меня есть следующая потребность, и я вижу много частичных решений, но я уверен, что я не первый человек, который будет нуждаться в этом, таким образом, я задаюсь вопросом, пропускаю ли я очевидное.

$client имеет 50-500-байтовую ценность двоичных данных, которые должны быть вставлены в середину URL и распространения в прямом и обратном направлениях к браузеру их клиента. Так как это - часть URL, мы противостоим 1K "теоретическому" пределу ПОЛУЧИТЬ URL. Кроме того, $client не хочет их клиента, декодирующего данные или вмешивающегося в них без обнаружения. $client также предпочел бы не хранить что-либо серверная сторона, таким образом, это должно быть абсолютно автономно. Должен быть код Perl, и быстро, и в кодировании и в декодировании.

Я думаю, что последний шаг может быть base64. Но каковы шаги для шифрования и хеширования, которые имеют большую часть смысла?

10
задан Randal Schwartz 24 May 2010 в 22:40
поделиться

4 ответа

У меня есть код в приложении Cat, который использует Crypt :: Util для кодирования / декодирования адреса электронной почты пользователя для ссылки для подтверждения электронной почты.

Я создал модель Crypt :: Util , используя Catalyst :: Model :: Adapter с секретным ключом. Затем в моем контроллере у меня есть следующая логика на отправляющей стороне:

my $cu = $c->model('CryptUtil');
my $token = $cu->encode_string_uri_base64( $cu->encode_string( $user->email ) );
my $url = $c->uri_for( $self->action_for('verify'), $token );

Я отправляю эту ссылку на $ user-> email , и когда на нее нажимают, я использую следующее.

my $cu = $c->model('CryptUtil');
if ( my $id = $cu->decode_string( $cu->decode_string_uri_base64($token) ) ) {
    # handle valid link
} else { 
    # invalid link
}

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

5
ответ дан 4 December 2019 в 01:00
поделиться

Насколько это должно быть безопасно? Не могли бы вы просто xor данных с длинной случайной строкой, а затем добавить хеш MD5 всей партии с другой секретной солью для обнаружения подделки?

Я бы не стал использовать это для банковских данных, но, вероятно, подойдет для большинства веб-вещи ...

большой

-1
ответ дан 4 December 2019 в 01:00
поделиться

Я вижу здесь три шага. Во-первых, попробуйте сжать данные. При таком малом количестве данных bzip2 может сэкономить вам 5-20%. Я бы поставил защиту, чтобы убедиться, что это не увеличит размер данных. Возможно, этот шаг не стоит того.

use Compress::Bzip2 qw(:utilities);
$data = memBzip $data;

Вы также можете попробовать уменьшить длину любых ключей и значений в данных вручную. Например, first_name можно сократить до fname.

Во-вторых, зашифруйте его. Выберите свой любимый шифр и используйте Crypt::CBC. Здесь я использую Rijndael, потому что он достаточно хорош для АНБ. Вы захотите провести сравнительный анализ, чтобы найти оптимальный баланс между производительностью и безопасностью.

use Crypt::CBC;
my $key = "SUPER SEKRET";
my $cipher = Crypt::CBC->new($key, 'Rijndael');
my $encrypted_data = $cipher->encrypt($data);

Вам придется хранить ключ на сервере. Помещения его в защищенный файл должно быть достаточно, защита этого файла остается в качестве упражнения. Когда вы говорите, что не можете хранить ничего на сервере, я предполагаю, что это не включает ключ.

Наконец, закодируйте его в Base 64. Я бы использовал модифицированный URL-safe base 64, который использует - и _ вместо + и /, что избавляет вас от необходимости тратить место URL на кодирование этих символов в строке base 64. MIME::Base64::URLSafe покрывает это.

use MIME::Base64::URLSafe;
my $safe_data = urlsafe_b64encode($encrypted_data);

Затем вставьте его в URL, как вам захочется. Проделайте обратный процесс для его считывания.

Вы должны быть спокойны за размер. Шифрование увеличит размер данных, но, вероятно, менее чем на 25%. Base 64 увеличит размер данных на треть (кодирование как 2^6 вместо 2^8). Таким образом, при кодировании 500 байт размер 1K будет комфортным.

3
ответ дан 4 December 2019 в 01:00
поделиться

Создайте секретный ключ и сохраните его на сервере. Если есть несколько серверов и запросы не обязательно вернутся на один и тот же сервер; вам нужно будет использовать один и тот же ключ на всех серверах. Этот ключ следует периодически поворачивать.

Если вы шифруете данные в режиме CBC (Cipher Block Chaining) (см. Модуль Crypt :: CBC), накладные расходы на шифрование составляют не более двух блоков (один для IV и один для заполнения). 128-битные (т.е. 16-байтовые) блоки являются обычными, но не универсальными. Я рекомендую использовать AES (он же Rijndael) в качестве блочного шифра.

Вам необходимо подтвердить данные, чтобы убедиться, что они не были изменены. В зависимости от безопасности приложения простого хеширования сообщения и включения хеша в зашифрованный открытый текст может быть достаточно. Это зависит от того, что злоумышленники не могут изменить хэш в соответствии с сообщением, не зная симметричного ключа шифрования. Если вы используете 128-битные ключи для шифра, используйте 256-битный хэш, например SHA-256 (для этого вы можете использовать модуль Digest). Вы также можете включить в данные некоторые другие вещи, например временную метку, чтобы запрос не повторялся несколько раз.

4
ответ дан 4 December 2019 в 01:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: