Ключевые слова:crypt, perl, howto, (найти похожие документы)
Date: Tue, 03 Dec 2002 21:32:26 +0500
From: Andrey Sapozhnikov <sapa@icb.chel.su>
Newsgroups: ftn.ru.cgi.perl
Subject: Шифрование данных в Perl программах
> Короче берешь на случайное число умножаешь и в следющем действии юзера
> делишь. или сдвигаешь на байт влево или вправо.
Криптостойкость подобного "шифра" в общем случае будет
чрезвычайно низка. Достаточно отметить, не проводя
дополнительного анализа стойкости, что данный "шифр"
абсолютно не отвечает принципу Кирхгофа. А
последовательность арифметических операций умножения
и деления вообще бессмысленна по той причине, что
(x * k1) / k2 = x * (k1 / k2), где константное
значение k1/k2 и будет являться ключом данного "шифра".
Я бы хотел отметить, что создание новых стойких
алгоритмов шифрования исключительно сложный процесс,
требующий большого объема математичиских доказательств
и если только Вы не специалист в области криптографии,
то заниматься подобным не только бесполезно, но и
вредно в силу создания иллюзий защищенности системы.
Лучше воспользоваться готовыми проверенными алгоритмами
криптования, хотя для того, чтоб их грамотно применить
вме равно нужны базовые знания в области криптографии.
Применительно к Perl я рекомендовал бы использовать
Crypt::Rijndael (Rijndael cipher, now AES)
Crypt::Rijndael_PP (pure-perl implementation)
Crypt::GOST (ГОСТ 28147-89)
Crypt::GOST_PP (pure-perl implementation)
Crypt::Twofish2
Crypt::IDEA
в большинстве случаев вместе с модулем
Crypt::CBC
и в качестве асиммметричных алгоритмов:
Crypt::DSA
Crypt::RSA
впрочем, для данной задачи они не нужны.
Приблизительная схема использования шифрования в данной
задаче (упрощенно-схематически):
1. Создание криптованного сообщения самому себе.
use Crypt::CBC;
my $plaintext = (time() + 180) . "&$param1&$param2";
my $cipher = Crypt::CBC->new( {
'key' => 't0p $eKreT |<eY',
'cipher' => 'Rijndael'
} );
my $ciphertext = $cipher->encrypt_hex($plaintext);
print "window.open('my_perl_script.cgi?p=$ciphertext', ",
"'mywin', 'height=200, width=300');\n";
2. Получение сообщения, декриптование, проверка валидности.
use CGI;
use Crypt::CBC;
use MIME::Base64;
my $ciphertext = param('p') or
die "mandatory parameter not passed";
my $cipher = Crypt::CBC->new( {
'key' => 't0p $eKreT |<eY',
'cipher' => 'Rijndael'
} );
my $plaintext = $cipher->decrypt_hex($ciphertext) or
die "decryption failed";
$plaintext =~ /^(\d+)&(\w+)&(\w+)$/ or
die "validation failed\n";
time() <= $1 or die "parameter expired";
my ($param1, $param2) = ($2, $3);
В данном случае модуль Crypt::CBC решает за нас
несколько задач - дополнение ключа и данных до
размера блока требуемого данному алгоритму
криптования, генерацию случайного IV (начального
вектора), криптование и упаковку результата
в строку.
From: Andrey Sapozhnikov <sapa@icb.chel.su>
> У них в сишной-то реализации ассемблерными вставками народ развлекается, а ты
> pure perl хочешь... Они ж с открытым ключом, они тяжелые по определению.
IDEA и Twofish - это симметричные алгоритмы (т.е. с закрытым ключом).
Кстати, я тут проделал небольшой сравнительный бенчмарк сайферов.
Сайферы которые не умеют работать с Crypt::CBC - выбросил, за
исключением GOST_PP - его поправить оказалось проще простого
(причем не изменяя сам модуль).
Benchmark: running Blowfish, Blowfish_PP, CAST5, CAST5_PP, DES, DES_EDE3,
DES_PP, GOST, GOST_PP, IDEA, Rijndael, Rijndael_PP, Serpent, TEA, Twofish,
Twofish2 for at least 5 CPU seconds...
Blowfish: 5 wallclock secs ( 5.33 usr + 0.00 sys = 5.33 CPU) @ 1201.69/s
(n=6405)
Blowfish_PP: 6 wallclock secs ( 5.08 usr + 0.00 sys = 5.08 CPU) @ 6.69/s
(n=34)
CAST5: 6 wallclock secs ( 5.26 usr + 0.00 sys = 5.26 CPU) @ 1459.89/s
(n=7679)
CAST5_PP: 5 wallclock secs ( 5.08 usr + 0.12 sys = 5.20 CPU) @ 124.23/s
(n=646)
DES: 6 wallclock secs ( 5.31 usr + 0.00 sys = 5.31 CPU) @ 1391.53/s
(n=7389)
DES_EDE3: 5 wallclock secs ( 5.30 usr + 0.01 sys = 5.31 CPU) @ 1076.84/s
(n=5718)
DES_PP: 6 wallclock secs ( 5.10 usr + 0.02 sys = 5.12 CPU) @ 549.80/s
(n=2815)
GOST: 5 wallclock secs ( 5.15 usr + 0.01 sys = 5.16 CPU) @ 1365.31/s
(n=7045)
GOST_PP: 7 wallclock secs ( 4.57 usr + 0.70 sys = 5.27 CPU) @ 135.10/s
(n=712)
IDEA: 5 wallclock secs ( 5.23 usr + 0.01 sys = 5.24 CPU) @ 1383.97/s
(n=7252)
Rijndael: 6 wallclock secs ( 5.34 usr + 0.00 sys = 5.34 CPU) @ 1362.73/s
(n=7277)
Rijndael_PP: 5 wallclock secs ( 5.25 usr + 0.06 sys = 5.31 CPU) @ 54.80/s
(n=291)
Serpent: 5 wallclock secs ( 5.26 usr + 0.02 sys = 5.28 CPU) @ 1235.42/s
(n=6523)
TEA: 6 wallclock secs ( 5.25 usr + 0.00 sys = 5.25 CPU) @ 1332.00/s
(n=6993)
Twofish: 5 wallclock secs ( 5.29 usr + 0.00 sys = 5.29 CPU) @ 1258.22/s
(n=6656)
Twofish2: 6 wallclock secs ( 5.30 usr + 0.00 sys = 5.30 CPU) @ 1303.21/s
(n=6907)
Вот код замерялки:
---------------------------------------------------------------------
#!/usr/bin/perl -w
use strict;
use Crypt::CBC;
use Benchmark;
sub Crypt::GOST_PP::keysize { 32 }
sub Crypt::GOST_PP::blocksize { 8 }
my @ciphers = qw(
Blowfish Blowfish_PP
GOST GOST_PP
CAST5 CAST5_PP
DES_EDE3
DES DES_PP
Rijndael Rijndael_PP
Serpent Twofish Twofish2
IDEA TEA
);
my %dotest;
foreach (@ciphers) {
my $cipher = "Crypt::$_";
$dotest{$_} = sub {
my $c = Crypt::CBC->new( {
'key' => '12341234',
'cipher' => "$cipher"
} );
$c->decrypt($c->encrypt('test line')) eq 'test line' or
die "cipher error";
};
}
timethese -5, \%dotest;
------------------------------ EOF ---------------------------
Самым быстрым из pure-perl оказался DES_PP. Из сайферов с
большим размером ключа наиболее быстрые GOST_PP и CAST5_PP.
Blowfish_PP - в пролете, скорость черепашья. А вот Rijndael_PP
вполне себе неплох, хотя вдвое медленнее CAST5_PP. C-шные
реализации показали близкую скорость, очевидно решающим
фактором тут уже становится Crypt::CBC. Отказ от регенерации
ключа в Crypt::CBC не приводит к заметному ускорению -
Digest::MD5 чрезвычайно быстр. Hа моей машине (P4 1.7GHz) он
показывает 307235.08/s.
под линух используем CPAN - все работает без проблем
а под виндами чуть сложнее :) работаем через PPM
1. Добавляем новый репоситорий
rep add Crypt http://theoryx5.uwinnipeg.ca/ppms/