package Crypt::DH::GMP;
use 5.0080001;
use strict;
use warnings;
use vars qw($VERSION @ISA);
$VERSION = '0.00012';
eval {
require XSLoader;
XSLoader::load(__PACKAGE__, $VERSION);
1;
} or do {
require DynaLoader;
push @ISA, 'DynaLoader';
__PACKAGE__->bootstrap($VERSION);
};
sub import
{
my $class = shift;
if (grep { $_ eq '-compat' } @_) {
require Crypt::DH::GMP::Compat;
}
}
sub new
{
my $class = shift;
my %args = @_;
$class->_xs_create($args{p} || "0", $args{g} || "0", $args{priv_key} || '');
}
*compute_secret = \&compute_key;
1;
__END__
=head1 NAME
Crypt::DH::GMP - Crypt::DH Using GMP Directly
=head1 SYNOPSIS
use Crypt::DH::GMP;
my $dh = Crypt::DH::GMP->new(p => $p, g => $g);
my $val = $dh->compute_secret();
# If you want compatibility with Crypt::DH (it uses Math::BigInt)
# then use this flag
# You /think/ you're using Crypt::DH, but...
use Crypt::DH::GMP qw(-compat);
my $dh = Crypt::DH->new(p => $p, g => $g);
my $val = $dh->compute_secret();
=head1 DESCRIPTION
Crypt::DH::GMP is a (somewhat) portable replacement to Crypt::DH, implemented
mostly in C.
=head1 RATIONALE
In the beginning, there was C. However, C suffers
from a couple of problems:
=over 4
=item GMP/Pari libraries are almost always required
C works with a plain C, but if you want to use
it in production, you almost always need to install C
or C because without them, the computation that is
required by C makes the module pretty much unusable.
Because of this, C might as well make C a
hard requirement.
=item Crypt::DH suffers from having Math::BigInt in between GMP
With or without C or C, C
makes several round trip conversions between Perl scalars, Math::BigInt objects,
and finally its C representation (if GMP/Pari are installed).
Instantiating an object comes with a relatively high cost, and if you make
many computations in one go, your program will suffer dramatically because
of this.
=back
These problems quickly become apparent when you use modules such as
C, which requires to make a few calls to C.
C attempts to alleviate these problems by providing a
C-compatible layer, which, instead of doing calculations via
Math::BigInt, directly works with libgmp in C.
This means that we've essentially eliminated 2 call stacks worth of
expensive Perl method calls and we also only load 1 (Crypt::DH::GMP) module
instead of 3 (Crypt::DH + Math::BigInt + Math::BigInt::GMP).
These add up to a fairly significant increase in performance.
=head1 COMPATIBILITY WITH Crypt::DH
Crypt::DH::GMP absolutely refuses to consider using anything other than
strings as its parameters and/or return values therefore if you would like
to use Math::BigInt objects as your return values, you can not use
Crypt::DH::GMP directly. Instead, you need to be explicit about it:
use Crypt::DH;
use Crypt::DH::GMP qw(-compat); # must be loaded AFTER Crypt::DH
Specifying -compat invokes a very nasty hack that overwrites Crypt::DH's
symbol table -- this then forces Crypt::DH users to use Crypt::DH::GMP
instead, even if you are writing
my $dh = Crypt::DH->new(...);
$dh->compute_key();
=head1 BENCHMARK
By NO MEANS is this an exhaustive benchmark, but here's what I get on my
MacBook (OS X 10.5.8, 2.4 GHz Core 2 Duo, 4GB RAM)
Benchmarking instatiation cost...
Rate pp gmp
pp 9488/s -- -79%
gmp 45455/s 379% --
Benchmarking key generation cost...
Rate gmp pp
gmp 6.46/s -- -0%
pp 6.46/s 0% --
Benchmarking compute_key cost...
Rate pp gmp
pp 12925/s -- -96%
gmp 365854/s 2730% --
=head1 METHODS
=head2 new
=head2 p
=head2 g
=head2 compute_key
=head2 compute_secret
=head2 generate_keys
=head2 pub_key
=head2 priv_key
=head2 compute_key_twoc
Computes the key, and returns a string that is byte-padded two's compliment
in binary form.
=head2 pub_key_twoc
Returns the pub_key as a string that is byte-padded two's compliment
in binary form.
=head2 clone
=head1 AUTHOR
Daisuke Maki C<< >>
=head1 LICENSE
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.
See http://www.perl.com/perl/misc/Artistic.html
=cut