File Coverage

blib/lib/Crypt/OpenPGP/Key/Public/ElGamal.pm
Criterion Covered Total %
statement 56 59 94.9
branch 4 4 100.0
condition 1 3 33.3
subroutine 19 22 86.3
pod 3 9 33.3
total 83 97 85.5


line stmt bran cond sub pod time code
1             package Crypt::OpenPGP::Key::Public::ElGamal;
2 6     6   71 use strict;
  6         15  
  6         475  
3              
4             our $VERSION = '1.19'; # VERSION
5              
6 6     6   50 use Crypt::OpenPGP::Util qw( bitsize);
  6         12  
  6         467  
7 6     6   43 use Crypt::OpenPGP::Key::Public;
  6         13  
  6         288  
8 6     6   41 use Crypt::OpenPGP::ErrorHandler;
  6         16  
  6         231  
9 6     6   33 use base qw( Crypt::OpenPGP::Key::Public Crypt::OpenPGP::ErrorHandler );
  6         14  
  6         2890  
10              
11 15     15 1 83 sub can_encrypt { 1 }
12 0     0 0 0 sub abbrev { 'g' }
13              
14 98     98 0 446 sub public_props { qw( p g y ) }
15 13     13 0 72 sub crypt_props { qw( a b ) }
16 0     0 0 0 sub sig_props { qw( a b ) }
17              
18 12     12 1 107 sub size { bitsize($_[0]->p) }
19              
20             sub init {
21 36     36 0 95 my $key = shift;
22 36   33     320 $key->{key_data} = shift || Crypt::OpenPGP::ElGamal::Public->new;
23 36         243 $key;
24             }
25              
26             sub keygen {
27 0     0 1 0 return $_[0]->error("ElGamal key generation is not supported");
28             }
29              
30             sub encrypt {
31 12     12 0 56 my $key = shift;
32 12         38 my($M) = @_;
33 12         75 $key->{key_data}->encrypt($M);
34             }
35              
36             package Crypt::OpenPGP::ElGamal::Public;
37 6     6   53 use strict;
  6         16  
  6         255  
38              
39 6     6   63 use Crypt::OpenPGP::Util qw( mod_exp );
  6         23  
  6         408  
40 6     6   42 use Math::BigInt;
  6         14  
  6         71  
41              
42 36     36   220 sub new { bless {}, $_[0] }
43              
44             sub encrypt {
45 12     12   30 my $key = shift;
46 12         30 my($M) = @_;
47 12         45 my $k = gen_k($key->p);
48 12         65 my $a = mod_exp($key->g, $k, $key->p);
49 12         31360598 my $b = mod_exp($key->y, $k, $key->p);
50 12         33574150 $b->bmod($key->p);
51 12         6357 { a => $a, b => $b * $M };
52             }
53              
54             sub gen_k {
55 12     12   29 my($p) = @_;
56             ## XXX choose bitsize based on bitsize of $p
57 12         25 my $bits = 198;
58 12         51 my $p_minus1 = Math::BigInt->new($p);
59 12         2034 $p_minus1->bsub(1);
60              
61 12         4025 my $k = Crypt::OpenPGP::Util::get_random_bigint($bits);
62 12         33 while (1) {
63 19 100       612 last if Math::BigInt::bgcd($k, $p_minus1) == 1;
64 7         96494 $k++;
65             }
66 12         189500 $k;
67             }
68              
69             sub _getset {
70 18     18   42 my $e = shift;
71             sub {
72 156     156   398 my $key = shift;
73 156 100       647 $key->{$e} = shift if @_;
74 156         954 $key->{$e};
75             }
76 18         102 }
77              
78             *p = _getset('p');
79             *g = _getset('g');
80             *y = _getset('y');
81              
82             1;