Llew_Llaw_Gyffes has asked for the wisdom of the Perl Monks concerning the following question:
Brethren,
I have a threaded Perl ICB client which features client-side end-to-end encryption. It's been working fine for years using Crypt::DH and Crypt::Blowfish (plus supporting modules of course). Crypt::DH is used to create a shared one-time key for Blowfish. I just tried to update my application to use Crypt::DH::GMP, in order to improve performance and reduce the number of module dependencies, and I'm running into an error that I don't fully understand.
Here are the relevant bits of code:
use Module::Load::Conditional qw[can_load check_install requires]; $Module::Load::Conditional::VERBOSE = 1; my $crypt_mods = {'Crypt::DH::GMP' => undef, 'Crypt::CBC' => undef, 'Crypt::Blowfish' => undef, 'Digest::SHA' => undef, 'MIME::Base64' => undef, 'Compress::Zlib' => undef}; if (can_load(modules => $crypt_mods, verbose => 1)) { $encryption_avail = 1; } my ($DH_public, $DH_public2, $DH_private, $DH_secret); [...] sub create_public_key { my $to = lc($_[0]); my $from = lc($_[1]); my $player = $_[2]; my ($DH, $p, $g, $i, $public, @chars); @chars = split(//,($player ? $to : $from)); $g = ord(shift(@chars)); while (scalar @chars) { $g += ord(shift(@chars)); } @chars = split(//, ($player ? $from : $to)); $i = ord(shift(@chars)); while (scalar @chars) { $i += ord(shift(@chars)); } $i %= scalar(@EICB_PRIMES); $p = $EICB_PRIMES[$i]; $DH = Crypt::DH::GMP->new; $DH->g($g); $DH->p($p); $DH->generate_keys; $DH_public = $DH->pub_key; $DH_private = $DH->priv_key; } sub create_secret_key { my $to = lc($_[0]); my $from = lc($_[1]); my $player = $_[2]; my ($DH, $p, $g, $i, $public, @chars); @chars = split(//,($player ? $to : $from)); $g = ord(shift(@chars)); while (scalar @chars) { $g += ord(shift(@chars)); } @chars = split(//,($player ? $from : $to)); $i = ord(shift(@chars)); while (scalar @chars) { $i += ord(shift(@chars)); } $i %= scalar(@EICB_PRIMES); $p = $EICB_PRIMES[$i]; $DH = Crypt::DH::GMP->new; $DH->g($g); $DH->p($p); $DH->priv_key($DH_private); $DH->generate_keys; $DH_secret = $DH->compute_secret($DH_public2); } [...] sub do_crypt_command { my ($who, $args, $time) = @_; my @args = split(/\s+/, $args); my $command = shift (@args); if ($command == $EICB_DH_INIT) { create_public_key($who, $cur_nick, 0); $connection->sendpriv($who, sprintf('%s%s %s', $EICB_CRYPT_PREFIX, $EICB_DH_REPLY, $DH_public)); } elsif ($command == $EICB_DH_REPLY) { $DH_public2 = shift(@args); create_public_key($who, $cur_nick, 1); $connection->sendpriv($who, sprintf('%s%s %s', $EICB_CRYPT_PREFIX, $EICB_DH_REPLY2, $DH_public)); create_secret_key($who, $cur_nick, 1); } elsif ($command == $EICB_DH_REPLY2) { $DH_public2 = shift(@args); create_secret_key($who, $cur_nick, 0); my $sha1 = Digest::SHA->new; $sha1->add($logbuffer[rand(scalar @logbuffer)]); my $key = $sha1->b64digest; $session_keys{lc($who)} = $key; encrypt(\$key, $cipher, $DH_secret); $connection->sendpriv($who, sprintf('%s%s %s', $EICB_CRYPT_PREFIX, $EICB_SESSION_KEY, $key)); timestamp($time) if ($timestamps_active); icb_print ($output_window, 'sbrkt', "%s", "[="); icb_print ($output_window, 'status', "%s", "SECURE"); icb_print ($output_window, 'sbrkt', "%s", "=]"); icb_print ($output_window, 'status', " Session key for user %s established\n", $who); $tabhist{lc($who)} = time(); } [...]
Logic flow is as follows: When client A requests an encrypted session with client B, A sends B a cleartext message containing an EICB_DH_INIT request. If B has encryption enabled, B calls create_public_key( ) and sends its public key back to A in a EICB_DH_REPLY message. A receives the EICB_DH_REPLY message, calls create_public_key( ) to create its own public key, and sends that back to B in a EICB_DH_REPLY2 message. A and B then both call create_secret_key( ), and B generates a one-time Blowfish session key and sends it back to A encrypted using the shared DH secret.
Using Crypt::DH, all of this works. Using Crypt::DH::GMP, create_public_key( ) works, but create_secret_key( ) fails at the $DH->priv_key($DH_private) statement:
Thread 3 terminated abnormally: Usage: Crypt::DH::GMP::priv_key(dh) at + ./icbm line 2434.
I'm not quite sure what I need to change here. The limited documentation in Crypt::DH::GMP does not make any mention of any change in usage of the priv_key( ) method.
Can anyone point out what I'm doing wrong?
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Usage problem with Crypt::DH::GMP::priv_key( )
by syphilis (Archbishop) on Mar 08, 2016 at 02:10 UTC | |
by Llew_Llaw_Gyffes (Scribe) on Mar 08, 2016 at 05:05 UTC | |
by Llew_Llaw_Gyffes (Scribe) on Mar 08, 2016 at 14:54 UTC |