blob: a6f589c0f8291625ffa12321f246f9b84fc3ae5a (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
|
package Crypt::OpenPGP::Key::Public::ElGamal;
use strict;
use Crypt::OpenPGP::Util qw( bitsize);
use Crypt::OpenPGP::Key::Public;
use Crypt::OpenPGP::ErrorHandler;
use base qw( Crypt::OpenPGP::Key::Public Crypt::OpenPGP::ErrorHandler );
sub can_encrypt { 1 }
sub abbrev { 'g' }
sub public_props { qw( p g y ) }
sub crypt_props { qw( a b ) }
sub sig_props { qw( a b ) }
sub size { bitsize($_[0]->p) }
sub init {
my $key = shift;
$key->{key_data} = shift || Crypt::OpenPGP::ElGamal::Public->new;
$key;
}
sub keygen {
return $_[0]->error("ElGamal key generation is not supported");
}
sub encrypt {
my $key = shift;
my($M) = @_;
$key->{key_data}->encrypt($M);
}
package Crypt::OpenPGP::ElGamal::Public;
use strict;
use Crypt::OpenPGP::Util qw( mod_exp );
use Math::Pari qw( Mod lift gcd );
sub new { bless {}, $_[0] }
sub encrypt {
my $key = shift;
my($M) = @_;
my $k = gen_k($key->p);
my $a = mod_exp($key->g, $k, $key->p);
my $b = mod_exp($key->y, $k, $key->p);
$b = Mod($b, $key->p);
$b = lift($b * $M);
{ a => $a, b => $b };
}
sub gen_k {
my($p) = @_;
## XXX choose bitsize based on bitsize of $p
my $bits = 198;
my $p_minus1 = $p - 1;
require Crypt::Random;
my $k = Crypt::Random::makerandom( Size => $bits, Strength => 0 );
while (1) {
last if gcd($k, $p_minus1) == 1;
$k++;
}
$k;
}
sub _getset {
my $e = shift;
sub {
my $key = shift;
$key->{$e} = shift if @_;
$key->{$e};
}
}
*p = _getset('p');
*g = _getset('g');
*y = _getset('y');
1;
|