Moduł Crypt::RSA

Uniwersytet Gdański - Instytut Matematyki - Zakład Informatyki - Strona domowa

Co to jest

RSA to pierwszy i obecnie jeden z dwóch najpopularniejszych (obok ElGamala) algorytmów kryptografii asymetrycznej (klucz publiczny/prywatny). RSA opiera się na trudności faktoryzacji dużych liczb, może też być używane do podpisów cyfrowych. Moduł ten jest implementacją kryptosystemu klucza publicznego RSA. Crypt::RSA wprowadza tworzenie kluczy, szyfrowanie/deszyfrowanie oraz podpis cyfrowy, autorem jest Vipul Ved Prakash.

Download

Zależności

Wymagana jest instalacja między innymi nastepujących modułów

Instalacja w systemie UNIX'owym

Po rozpakowaniu modułu wydajemy polecenie

perl Makefile.PL make make install

Sprawdzamy, czy został on pomyślnie zainstalowany, pisząc jednolinijkowca perl -e 'use Crypt::RSA' Pomyślne wykonanie programu (żadnych komunikatów) daje nadzieję, że moduł został zainstalowany poprawnie i będzie działał. Jeżeli wszystko poszło zgodnie z planem to możemy już korzystać z możliwości naszego nowego modułu.

Konstruktor

my $rsa = Crypt::RSA->new();

Jeżeli nie podaliśmy żadnych argumentów new(), zwróci obiekt z domyślnymi wartościami. Ten obiekt może być dostosowany do naszych potrzeb przez określenie schematów szyfrowania, podpisu, formatu klucza.

Modyfikowanie obiektu Crypt::RSA

Nasz obiekt może być modyfikowny przez umieszczenie kluczy w konstruktorze new(). Wartość powiązana z tymi kluczami może być zarówno nazwą (stringiem) lub też referencją do hasza, która określa nazwę modułu, konstruktor i jego argumenty. Na przykład:

my $rsa = new Crypt::RSA ( ES => 'OAEP' );
lub

my $rsa = new Crypt::RSA ( ES => { Module => 'Crypt::RSA::ES::OAEP' } );
Rozpoznawane są następijące nazwy:

Metody

keygen()
Generuje oraz zwraca parę kluczy RSA o podanej długości bitów.
encrypt()
Przeprowadza szyfrowanie na stringu o ustalonej długości, używając publicznego klucza. Domyślnym schematem jest OAEP. Szyfrowanie jeżeli się powiedzie, zwraca szyfrogram w formie stringa, w przeciwnym wypadku zwraca undef. Parametrami jest hasz z nastepującymi kluczami:

  • Message - Ustalonej długości string, który ma zostać zaszyfrowany.
  • Key - Publiczny klucz odbiorcy.
  • Armour - Parametr BOOL, który zmusza nasz szyfrogram do poddania się różnym procesom podczas szyfrowania. Domyślnie używany jest tryb Convert::ASCII::Armour, który koduje binarne oktety w 6-bitowe, czyste wiadomości ASCII.

decrypt()
Przeprowadza deszyfrowanie z użyciem klucza prywatnego, ograniczone przez schemat obiektu. Domyślnym schematem jest OAEP Deszyfrowanie zwraca tekst jawny jeżeli wszystko się powiodło, w przeciwnym wypadku zwraca undef. Parametrami jest hasz z następującymi kluczami:

  • Cyphertext - Ustalonej długości szyfrogram.
  • Key - Prywatny klucz.
  • Armour - Parametr BOOL, który określa, czy nasz szyfrogram był kodowany.

sign()
Tworzy podpis RSA pod wiadomością, używając prywatnego klucza oraz schematu ograniczonego przez obiekt. Domyślnym schematem jest PSS. Jeżeli wszystko się powiodło sign() zwraca podpis, w przeciwnym wypadku undef. Parametrami jest hasz z następującymi kluczami:

  • Message - String o określonej długości, który ma zostać podpisany.
  • Key - Prywatny klucz nadawcy.
  • Armour - Parametr BOOL, który określa, czy nasz podpis ma być kodowany.

verify()
Weryfikuje podpis publicznym kluczem, używając schematu podpisu ograniczonego przez obiekt. Domyślnie jest PSS. Zwraca true jeżeli wszystko się powiodło, w przeciwnym wypadku udnef. Parametrami jest hasz z następującymi kluczami:

  • Message - Podpisana wiadomość o określonej długości.
  • Key - Publiczny klucz podpisującego.
  • Sign - Podpis obliczony przez sign().
  • Armour - Parametr BOOL, który określa, czy nasz podpis był kodowany.

Przykłady

Zad.1

Pierwszy program będzie polegał na wykonaniu oczywistej rzeczy, czyli wytworzeniu pary kluczy prywatnego i publicznego dla naszego użytkownika Bolka. Klucz prywatny oczywiście ukrywamy przed światem, publiczny umieszczamy na witrynie lub wysyłamy do osoby z którą bedziemy korespondować. Po wykonaniu, otrzymamy dwa pliki bolek.public oraz bolek.private

use strict; use Crypt::RSA; #Konstruktor my $rsa = new Crypt::RSA; #Tworzymy klucze my ($public, $private) = $rsa->keygen ( Identity => 'Perlowy Bolek', Size => 1024, Password => 'Jakies super tajne haslo', Verbosity => 1, ) or die $rsa->errstr(); #Zapis do plików $public->write ( Filename => 'bolek.public' ); $private->write ( Filename => 'bolek.private' );

Oto co znajduje się w pliku z kluczem prywatnym (klucze, ze względu na swoją długość zapisane zostały w postaci połączonych napisów)

$VAR1 = bless( { 'Version' => '1.91', 'Checked' => 0, 'Identity' => 'Perlowy Bolek', 'private_encrypted' => bless( { '_phi' => 'Blowfish 4dACGrtiuTkHyg4K7JRtyw 53616c7465645f5fb3428a88f1620b18b2ceb48375ba18' .'c7e0c0b00ac426ac86adc50a2c46b137a864a5a1305f64519cacf22e49eec91f72dd136fefc96ec956b86' .'e32b94543958d3b4d6979b4971cc6860264c9ff6d5b6ac84ce572a564959b349e79fea30b95dc118c7378' .'b31db7382d56bfee864cb6bc07fd7f4d9a5e8cc7f2ea25fdfadd241bf4aec27aeb122d1436ac7d2b793e6' .'fe4dcc53274626c269dc785e91cb6fd7f1f881df3eb7fc30e3bd4a63a53609445e744f84c83c5318ad1e1' .'d54f7aee88e0c36f00a64cbff76892b8380a82bcef716f678726cc7d24b8df0ed9512ab17560123b01042' .'4c7e6ded8815ee877071d1966785980233173c7646129065ef3a6ae1b242a83a985c0fac739cea7743171' .'8c0d44260f263107f2c3c1588e890b428934e5211980c6cf92007804d88c080337fd2a78fe61c2e69a55a' .'e7e07c128f0a82f', '_n' => 'Blowfish PN5EUKQqJ7f2r4vjD6T05Q 53616c7465645f5f5714151a124bec7dea8a29fac8b231ca' .'3ad298fe36ba5c43a61e4034c9bff5cda6950945d277479d86a16f572d689c2386356464c561c2bea66edb2' .'de8b529a2ea5daa8301def7d2b6c9ac21fd561e4ccebd9884d1ab7d330fb343a4441ccfbae3acea38ce46a8' .'e623ee27fabe159638ed471dbb333424dc379177ac24ca4cd679d055b7c7b8b8786ccabac1b963f46ce0a7c' .'97d51af0b22d1c9ecb6ab08edc2cb8f0f6233ed389f4bc041d921ad9b1314b457c88ba12a4e06087718c8e6' .'b805ed48169dd9f8ac6e29355dc8bb5f51e4cbc19590d151a8fcb720b3ef5d08ad198c26b92aab37b30ef99' .'10645747a71b273c718a6ca64303cf31bc0536cd34a685f60ea7a3ed22290589b5baa4f03849153a493816d' .'8be6d4c59283afe7d428f1e1290dd6c4a244eaea6c5a4a42f2df57d14a0c68a1a84d68ecd4256ce928284d', '_q' => 'Blowfish qLpKqUUzMGPnXX6//Gh+oA 53616c7465645f5f18438f039be83c83b265b732759f3d59' .'6a4687a129c6dd7f91b12608de46c05241c9455c4e934dccbee97cb9de06786674821464606eff2937bcf42' .'280646b47234d8521d67e7f6d2d15dbdfc46866bf79a361dc7930b345fe9b5e532dfdc1d6d1f746ac0836a0' .'de9a8e80969f18042d875db494201bddf361d192dba3b2898b14138148af341e8e12ef545903ab674490bf1' .'cd929e63c0ac43e62aaae2b392e24dd625f88fba5d0', '_p' => 'Blowfish LfijcC1vGCMKQdl6b5tu8A 53616c7465645f5f3f215c48e82c718e06bd7c4c1957c48a' .'13a5f3d937146f1c26f10b95205045f8d3b72243fc9077818b49ef22327ef1238ad050d4c76efc09115a7f5' .'b4437a348216398f9c88aead9354850acaf43a97fd2c8e76d4bd4e873d3f806266c5da06468a7c742bd97d5' .'79cb30fad86c44aad64486badcd0c8dc6573796b29a3e263d65d6a1c7819f612efcde1f269e162ad19a492c' .'4fff99eceb1a25fa74d24e82381eab63df4b4f92fa2', '_dp' => 'Blowfish nrK2iFcYZShoTuXf55paow 53616c7465645f5f69e8729326e4c9cd2ca339b5682aa73' .'43aca505613367099c232963c9bbeaedf726584071f1ee03fc753a7ba46daf31bd99baf6b4e531fb7699c34' .'61176244c5ab6e786526217f0332fc8a500b5448af2e5ccde56707d2cc566cf7089565374ef8312f5b650e0' .'075dfa7e7102c1f9af48da81a1882edbc84487a5ab120673913ecdb1d331462b2a62b09a3c3681faef92963' .'45c3d2a3dfa74940b60204a6af57bada1c5e71afc171', '_u' => 'Blowfish 80AY89646663hYYQxh5msg 53616c7465645f5f1c8f9fd31c0479f5af0f408fd20f03c8' .'0f824b2d8660ac3bcb86c00cc5fc61d849555af1367a25a81b1cd0c35486d8350a09b132f4be1e798ff1d9e' .'3f75aa45ff084165078a1c5007177a0cf212965cff329a992dc47ba12b1fc70c22ca834b9ef387b68efa336' .'62e662e62a9b803fe688027cf8576bc7ab1cfe781e78dd61251b337d589d4991a213eddb2aafc2ad023226a' .'6b6e477c45eb820c274d180d394c84b28bdb5ff212d', '_dq' => 'Blowfish nZosO/FzQCrR1E7BL8Ly6g 53616c7465645f5fc7a0c0496c19a423889c1b1c6e54eec' .'954fcb2d557c1edf903e9a1c53bda7719d8134a25b15b321d58283dbab9f81ca54c7ca6a15602ae8f8ba4fe' .'732f25ca6586a873071db03ffd0f8b2a08e640028cd7329628a8c4b2c6e529874ebd9e9c531848a254e2b0a' .'f0499f4fb6540af5d951a6ca16dc88d7d5da9c88d47d8f7e15eaeb66b3ce6872a41cd1ac5b625999ea06f65' .'865bf32ee53b20bce5be77e2bff8a935cc31dbe49c4b', '_d' => 'Blowfish YPvGOk1uD8tBoZWGOj0dcw 53616c7465645f5f9c4505c8d27e7542d42cbb6b594f1b0f' .'e0a4fbbd3ea99182b1eba5b2b11170ca1a2965fab4fd871d38455c450d7539d9b13b8d1b1883a5d6ecc1251' .'9e36dc6ca0971323c2ac5ee1a46ee4cc0468d5268c3f33fa1714ccc7c8cff08ad3607eab149c2bdf5cdc1c9' .'a54fb0a54a808194d889a0fd77680378d219483e00f539b3f4747a2341572ee5ec136bfe43ae3e1d670f78f' .'f36213e25df5883d76d04e27011023f8fcdc52d0293b53d3e9c26bb4db3efd6a427894183b39432ad18ecd3' .'46021bdd4e82d28c6c311ed4f06224864769314991cc69482e8039d68c1e3de892015351358e5178f966365' .'f18975480441b589e5e788f28b44c4f963ad418282d2627c2b9fa6b9b616f7d14546446c1eebca705b3932c' .'8028ee60824eb5234a63bca13d3a165b180ed0fec54d3c97b165c0870f68cdb33b8a8c79ac0128bc97781e', '_e' => 'Blowfish EzK9HcfPA2zj4wouO9lMww 53616c7465645f5f240691173387e0620502f446d0fb8179' }, 'Tie::EncryptedHash' ), 'Cipher' => 'Blowfish' }, 'Crypt::RSA::Key::Private' );

Oto co znajduje się w pliku z kluczem publicznym

$VAR1 = bless( { 'e' => 65537, 'n' => '15353017031904116536186079670430401116147966197878167534087483224936190254755927668824' .'6745918885876405701852718164280241875337096906893546900406088420925075610746400998338874' .'5284809325206706007513427805397010737560799244584195290717800509599142015518037386960542' .'52540133836659883258187183663514768707586652637', 'Version' => '1.91', 'Identity' => 'Perlowy Bolek' }, 'Crypt::RSA::Key::Public' );

Zad.2

Drugi program ukazuje proces szyfrowania wiadomości, którą ma do przekazania Alicja Bolkowi, chce oczywiście to zrobić w sposób dyskretny.

use strict; use Crypt::RSA; #Konstruktor my $rsa = Crypt::RSA->new(); #Odczytujemy klucz publiczny Bolka my $bolekey = Crypt::RSA::Key::Public->new( Filename => 'bolek.public' ); #Wiadomość, którą chcemy przekazać my $message="To jest nasz tekst jawny, ciekawe czy po zakodowaniu i odkodowaniu będzie taki sam."; #Tworzymy szyfrogram my $cyphertext = $rsa->encrypt ( Message => $message, Key => $bolekey, Armour => 1, ) || die $rsa->errstr(); printf "Oto nasza wiadomość:\n\n$cyphertext"; #Zapisujemy szyfrogram do pliku, będziemy mogli wysłać go Bolkowi open(fh,'> szyfrogram.txt'); print fh $cyphertext; close(fh);

Oto nasz szyfrogram

zad2

Zad.3

Trzeci program ukazuje proces odszyfrowania (przez Bolka) wiadomości przesłanej przez Alicję jako szyfrogram. Porównaj wynik z treścią wiadomości z zadania drugiego.

use strict; use Crypt::RSA; #Konstruktor my $rsa = Crypt::RSA->new(); #Pobieramy prywatny klucz Bolka z pliku my $bolekey = Crypt::RSA::Key::Private->new( Filename => 'bolek.private' ); #Dodajemy hasło $bolekey->reveal ( Password => 'Jakies super tajne haslo'); #Wczytujemy szyfrogram open (fh, '< szyfrogram.txt'); my $cyphertext; while ( <fh>) { $cyphertext.= $_; } #Deszyfrujemy my $plaintext =$rsa->decrypt ( Cyphertext => $cyphertext, Key => $bolekey, Armour => 1, ) || die $rsa->errstr(); printf "Oto nasza wiadomość po odszyfrowaniu:\n\n$plaintext\n"; close (fh);

Oto nasz tekst jawny

zad3

Zad.4

Czwarty program tworzy podpis cyfrowy pod wiadomością, taki podpis wraz z wiadomością może być przesłany przez Bolka do Alicji, która będzie miała pewność, że wiadomość pochodzi od niego.

use strict; use Crypt::RSA; #Konstruktor my $rsa = new Crypt::RSA; #Pobieramy prywatny klucz Bolka z pliku my $bolekey = Crypt::RSA::Key::Private->new( Filename => 'bolek.private' ); #Dodajemy hasło $bolekey->reveal ( Password => 'Jakies super tajne haslo'); #Wiadomość, która ma być podpisana my $message="To jest nasz tekst jawny, ciekawe czy po zakodowaniu i odkodowaniu będzie taki sam."; #Podpis pod wiadomością my $signature = $rsa->sign ( Message => $message, Key => $bolekey ) || die $rsa->errstr(); printf $signature."\n"; #Zapis podpisu do pliku open(fh,'> sign.txt'); print fh $signature; close(fh);

Oto nasz podpis w ASCII (skrót 128 bitowy)

zad4

Zad.5

Piąty program weryfikuje podpis Bolka pod wiadomością przesłaną Alicji. Na początku użyliśmy podpisu Bolka, następnie chcieliśmy podszyć się pod niego i przekonać Alicję, że tą wiadomość przesłał Bolek. Niestety to się nie udało :)

use strict; use Crypt::RSA; #Konstruktor my $rsa = Crypt::RSA->new(); #Pobieramy prywatny klucz Bolka z pliku my $bolekey = Crypt::RSA::Key::Public->new( Filename => 'bolek.public' ); #Wiadomość, którą dostaliśmy od Bolka my $message="To jest nasz tekst jawny, ciekawe czy po zakodowaniu i odkodowaniu będzie taki sam."; #Wczytujemy podpis Bolka open (fh, '< sign.txt'); my $signature; while ( <fh>) { $signature.= $_; } close(fh); #Weryfikujemy podpis pod wiadomością my $verify = $rsa->verify ( Message => $message, Signature => $signature, Key => $bolekey ); if ($verify) { print "1. Ta wiadomość pochodzi od BOLKA, możesz ją przeczytać\n\n"; } else { print "1. Niestety ktoś probuje się podszyć pod BOLKA -- TA WIADOMOŚĆ NIE POCHODZI OD NIEGO !\n"; } $signature=""; #Próbujemy oszukać Alicję open (fh, '< sign2.txt'); while ( <fh>) { $signature.= $_; } my $verify = $rsa->verify ( Message => $message, Signature => $signature, Key => $bolekey ); if ($verify) { print "2. Ta wiadomość pochodzi od BOLKA, możesz ją przeczytać\n"; } else { print "2. Niestety ktoś probuje się podszyć pod BOLKA -- TA WIADOMOŚĆ NIE POCHODZI OD NIEGO !\n"; }

Wynik weryfikacji

zad5

Dodatkowe informacje

Moduł ten może być przydatny do zabezpieczania wszelkiego rodzaju wiadomości, nie dopuszczając do poznania ich treści przez niepowołane osoby, możemy również podpisywac nasze wiadomości, czy weryfikować ich nadawcę. Po dodatkowe informacje odsyłam na stronę z dokumenacją modułu.

Autor opracowania

Adrian Sielski

Email: adrian.sielski@gmail.com

Uniwersytet Gdański - Instytut Matematyki - Zakład Informatyki - Strona domowa - Perl - Wyklady
[c] Piotr Arłukowicz, materiały z tej strony udostępnione są na licencji GNU.