#! /usr/local/bin/perl -w use strict; # -------------------------------------------------------------------------- # the essence of RSA algorithm -- assymetrical\public-key cryptography # -------------------------------------------------------------------------- use Math::Pari qw(gcd PARI) ; my $msg = 'ibm%^&*"<>`' ; my $cipher = cipher->new() ; my @c = $cipher->cipher($msg) ; print "@c\n" ; print $cipher->decipher(\@c) . "\n" ; { package cipher ; use strict ; use Math::Pari qw(gcd PARI) ; my ($int, $p, $q, $n, $b, $tmpl) ; # declared here, or won't share BEGIN { $int = 40 ; $p = PARI("prime(".int(rand $int).")") ; # Pari: prime(n) -- the n-th prime $q = PARI("prime(".int(rand $int).")") ; $n = $p*$q ; $b = ($p-1)*($q-1) ; # s.t. 1 < e < (p-1)(q-1), gcd(r, b) = 1 $tmpl = 'C*' ; # template for pack, unpack } sub new { my $class = shift ; my $self = {} ; # - - - - - - - - - - - - - - - - - - - - - - - - - - do {$self->{e} = int rand $b ; } until (gcd($self->{e},$b)==1) ; $self->{e} = PARI $self->{e} ; # public key, along with $n $self->{d} = (1/$self->{e})%$b ; # private key # - - - - - - - - - - - - - - - - - - - - - - - - - - bless($self, ref($class) || $class) ; return $self ; } sub cipher { my $self = shift ; my @m = unpack($tmpl, shift) ; my @c ; map { $c[$_] = ($m[$_]**$self->{e})%$n } 0..$#m ; # encrypt -- c = (m ^ e) mod n return @c ; } sub decipher { my $self = shift ; my @c = @{shift(@_)} ; my @d ; map { $d[$_] = ($c[$_]**$self->{d})%$n } 0..$#c ; # decrypt -- m = (c ^ d) mod n return pack($tmpl, @d) ; } }