Crypt::DH::GMP - Crypt::DH Using GMP Directly
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();
Crypt::DH::GMP is a (somewhat) portable replacement to Crypt::DH, implemented mostly in C.
Crypt::DH uses Math::BigInt, which is a very feature-full and fast interface to perform high-precision math. However, with Crypt::DH, there exists several problems:
GMP and Pari are High precision math libraries which can be used from Math::BigInt. They are great tools, but require the installation of these C libraries.
Crypt::DH (and in turn, Math::BigInt) works without these modules, but when used without them, Crypt::DH is pretty much useless because of its poor performance. This makes the underlying C libraries a requirement.
Math::BigInt is (again) a god-sent for those of us who require high-precision math from within Perl, but within the usage case that goes from Crypt::DH, Math::BigInt, and finally to GMP|Pari, Crypt::DH suffers dramatically in terms of performance, mainly (I assume) from the fact that it requires several calls that round trip conversions between Perl and GMP.
Based on these, I've decided that it will probably benefit a fair amount of people by introducing a Crypt::DH compatible layer that directly works with the C layer of gmp.
This means that we've essentially eliminated 2 call stacks worth of Perl method calls (which are expensive) and we also only load the 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.
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();
By NO MEANS is this an exhaustive benchmark, but here's what I get on my MacBook (OS X 10.5.2, 2GHz Core 2 Duo, 2GB RAM)
daisuke@beefcake Crypt-DH-GMP$ perl -Mblib tools/benchmark.pl Rate pp gmp pp 1.70/s -- -98% gmp 112/s 6526% --
I want it to run for much longer duration, but the above was all I could get going at 1am on this particular day
Computes the key, and returns a string that is byte-padded two's compliment in binary form.
Returns the pub_key as a string that is byte-padded two's compliment in binary form.
Daisuke Maki <daisuke@endeworks.jp>
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.