File Coverage

blib/lib/Crypt/OpenPGP/Key/Public/ElGamal.pm
Criterion Covered Total %
statement 55 58 94.8
branch 4 4 100.0
condition 1 3 33.3
subroutine 19 22 86.3
pod 3 9 33.3
total 82 96 85.4


line stmt bran cond sub pod time code
1             package Crypt::OpenPGP::Key::Public::ElGamal;
2 3     3   16 use strict;
  3         5  
  3         136  
3              
4 3     3   16 use Crypt::OpenPGP::Util qw( bitsize);
  3         3  
  3         192  
5 3     3   15 use Crypt::OpenPGP::Key::Public;
  3         5  
  3         85  
6 3     3   15 use Crypt::OpenPGP::ErrorHandler;
  3         6  
  3         102  
7 3     3   18 use base qw( Crypt::OpenPGP::Key::Public Crypt::OpenPGP::ErrorHandler );
  3         5  
  3         1075  
8              
9 24     24 1 125 sub can_encrypt { 1 }
10 0     0 0 0 sub abbrev { 'g' }
11              
12 67     67 0 315 sub public_props { qw( p g y ) }
13 12     12 0 46 sub crypt_props { qw( a b ) }
14 0     0 0 0 sub sig_props { qw( a b ) }
15              
16 12     12 1 118 sub size { bitsize($_[0]->p) }
17              
18             sub init {
19 21     21 0 40 my $key = shift;
20 21   33     196 $key->{key_data} = shift || Crypt::OpenPGP::ElGamal::Public->new;
21 21         113 $key;
22             }
23              
24             sub keygen {
25 0     0 1 0 return $_[0]->error("ElGamal key generation is not supported");
26             }
27              
28             sub encrypt {
29 12     12 0 26 my $key = shift;
30 12         28 my($M) = @_;
31 12         69 $key->{key_data}->encrypt($M);
32             }
33              
34             package Crypt::OpenPGP::ElGamal::Public;
35 3     3   18 use strict;
  3         4  
  3         85  
36              
37 3     3   17 use Crypt::OpenPGP::Util qw( mod_exp );
  3         5  
  3         188  
38 3     3   19 use Math::BigInt;
  3         6  
  3         31  
39              
40 21     21   125 sub new { bless {}, $_[0] }
41              
42             sub encrypt {
43 12     12   30 my $key = shift;
44 12         25 my($M) = @_;
45 12         55 my $k = gen_k($key->p);
46 12         74 my $a = mod_exp($key->g, $k, $key->p);
47 12         16671504 my $b = mod_exp($key->y, $k, $key->p);
48 12         17250208 $b->bmod($key->p);
49 12         3920 { a => $a, b => $b * $M };
50             }
51              
52             sub gen_k {
53 12     12   27 my($p) = @_;
54             ## XXX choose bitsize based on bitsize of $p
55 12         81 my $bits = 198;
56 12         72 my $p_minus1 = $p - 1;
57              
58 12         65 my $k = Crypt::OpenPGP::Util::get_random_bigint($bits);
59 12         35 while (1) {
60 23 100       700 last if Math::BigInt::bgcd($k, $p_minus1) == 1;
61 11         104029 $k++;
62             }
63 12         113615 $k;
64             }
65              
66             sub _getset {
67 9     9   14 my $e = shift;
68             sub {
69 114     114   181 my $key = shift;
70 114 100       420 $key->{$e} = shift if @_;
71 114         593 $key->{$e};
72             }
73 9         36 }
74              
75             *p = _getset('p');
76             *g = _getset('g');
77             *y = _getset('y');
78              
79             1;