Initial Commit

This commit is contained in:
Riley Schneider
2025-12-03 16:38:10 +01:00
parent c5e26bf594
commit b732d8d4b5
17680 changed files with 5977495 additions and 2 deletions

View File

@@ -0,0 +1,12 @@
package Crypt::OpenPGP::Key::Public;
use strict;
use Crypt::OpenPGP::Key;
use Crypt::OpenPGP::ErrorHandler;
use base qw( Crypt::OpenPGP::Key Crypt::OpenPGP::ErrorHandler );
sub all_props { $_[0]->public_props }
sub is_secret { 0 }
sub public_key { $_[0] }
1;

View File

@@ -0,0 +1,53 @@
package Crypt::OpenPGP::Key::Public::DSA;
use strict;
use Crypt::DSA::Key;
use Crypt::OpenPGP::Key::Public;
use Crypt::OpenPGP::ErrorHandler;
use base qw( Crypt::OpenPGP::Key::Public Crypt::OpenPGP::ErrorHandler );
sub can_sign { 1 }
sub abbrev { 'D' }
sub init {
my $key = shift;
$key->{key_data} = shift || Crypt::DSA::Key->new;
$key;
}
sub keygen {
my $class = shift;
my %param = @_;
require Crypt::DSA;
my $dsa = Crypt::DSA->new;
my $sec = $dsa->keygen( %param );
my $pub = bless { }, 'Crypt::DSA::Key';
for my $e (qw( p q g pub_key )) {
$pub->$e( $sec->$e() );
}
($pub, $sec);
}
sub public_props { qw( p q g y ) }
sub sig_props { qw( r s ) }
sub y { $_[0]->{key_data}->pub_key(@_[1..$#_]) }
sub size { $_[0]->{key_data}->size }
sub verify {
my $key = shift;
my($sig, $dgst) = @_;
require Crypt::DSA;
my $dsa = Crypt::DSA->new;
my $dsa_sig = Crypt::DSA::Signature->new;
$dsa_sig->r($sig->{r});
$dsa_sig->s($sig->{s});
$dsa->verify(
Key => $key->{key_data},
Digest => $dgst,
Signature => $dsa_sig
);
}
1;

View File

@@ -0,0 +1,79 @@
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::BigInt;
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->bmod($key->p);
{ a => $a, b => $b * $M };
}
sub gen_k {
my($p) = @_;
## XXX choose bitsize based on bitsize of $p
my $bits = 198;
my $p_minus1 = $p - 1;
my $k = Crypt::OpenPGP::Util::get_random_bigint($bits);
while (1) {
last if Math::BigInt::bgcd($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;

View File

@@ -0,0 +1,82 @@
package Crypt::OpenPGP::Key::Public::RSA;
use strict;
use Crypt::RSA::Key::Public;
use Crypt::OpenPGP::Digest;
use Crypt::OpenPGP::Util qw( bitsize bin2mp mp2bin );
use Crypt::OpenPGP::Key::Public;
use Crypt::OpenPGP::ErrorHandler;
use base qw( Crypt::OpenPGP::Key::Public Crypt::OpenPGP::ErrorHandler );
sub can_encrypt { 1 }
sub can_sign { 1 }
sub abbrev { 'R' }
sub public_props { qw( n e ) }
sub crypt_props { qw( c ) }
sub sig_props { qw( c ) }
sub init {
my $key = shift;
$key->{key_data} = shift || Crypt::RSA::Key::Public->new;
$key;
}
sub keygen {
my $class = shift;
my %param = @_;
$param{Password} = $param{Passphrase};
require Crypt::RSA::Key;
my $chain = Crypt::RSA::Key->new;
my($pub, $sec) = $chain->generate( %param );
return $class->error( $chain->errstr ) unless $pub && $sec;
($pub, $sec);
}
sub size { bitsize($_[0]->{key_data}->n) }
sub check { $_[0]->{key_data}->check }
sub encrypt {
my $key = shift;
my($M) = @_;
require Crypt::RSA::Primitives;
my $prim = Crypt::RSA::Primitives->new;
my $c = $prim->core_encrypt( Key => $key->{key_data}, Plaintext => $M ) or
return $key->error($prim->errstr);
{ c => $c }
}
sub verify {
my $key = shift;
my($sig, $dgst) = @_;
my $k = $key->bytesize;
require Crypt::RSA::Primitives;
my $prim = Crypt::RSA::Primitives->new;
my $c = $sig->{c};
my $m = $prim->core_verify( Key => $key->{key_data}, Signature => $c) or
return;
$m = mp2bin($m, $k - 1);
my $hash_alg = Crypt::OpenPGP::Digest->alg($sig->{hash_alg});
my $M = encode($dgst, $hash_alg, $k - 1);
$m eq $M;
}
{
my %ENCODING = (
MD2 => pack('H*', '3020300C06082A864886F70D020205000410'),
MD5 => pack('H*', '3020300C06082A864886F70D020505000410'),
SHA1 => pack('H*', '3021300906052B0E03021A05000414'),
);
sub encode {
my($dgst, $hash_alg, $mlen) = @_;
my $alg = $ENCODING{$hash_alg};
my $m = $alg . $dgst;
my $padlen = $mlen - length($m) - 2;
my $pad = chr(255) x $padlen;
chr(1) . $pad . chr(0) . $m;
}
}
1;

View File

@@ -0,0 +1,21 @@
package Crypt::OpenPGP::Key::Secret;
use strict;
use Crypt::OpenPGP::Key;
use Crypt::OpenPGP::ErrorHandler;
use base qw( Crypt::OpenPGP::Key Crypt::OpenPGP::ErrorHandler );
sub is_secret { 1 }
sub all_props { ($_[0]->public_props, $_[0]->secret_props) }
sub public_key {
my $key = shift;
my @pub = $key->public_props;
my $pub = Crypt::OpenPGP::Key::Public->new($key->alg);
for my $e (@pub) {
$pub->$e($key->$e());
}
$pub;
}
1;

View File

@@ -0,0 +1,39 @@
package Crypt::OpenPGP::Key::Secret::DSA;
use strict;
use Crypt::DSA::Key;
use Crypt::OpenPGP::Key::Public::DSA;
use Crypt::OpenPGP::Key::Secret;
use Crypt::OpenPGP::ErrorHandler;
use base qw( Crypt::OpenPGP::Key::Secret Crypt::OpenPGP::ErrorHandler );
sub secret_props { qw( x ) }
*sig_props = \&Crypt::OpenPGP::Key::Public::DSA::sig_props;
*public_props = \&Crypt::OpenPGP::Key::Public::DSA::public_props;
*size = \&Crypt::OpenPGP::Key::Public::DSA::size;
*keygen = \&Crypt::OpenPGP::Key::Public::DSA::keygen;
*can_sign = \&Crypt::OpenPGP::Key::Public::DSA::can_sign;
sub init {
my $key = shift;
$key->{key_data} = shift || Crypt::DSA::Key->new;
$key;
}
sub y { $_[0]->{key_data}->pub_key(@_[1..$#_]) }
sub x { $_[0]->{key_data}->priv_key(@_[1..$#_]) }
sub sign {
my $key = shift;
my($dgst) = @_;
require Crypt::DSA;
my $dsa = Crypt::DSA->new;
my $sig = $dsa->sign(
Key => $key->{key_data},
Digest => $dgst,
);
}
*verify = \&Crypt::OpenPGP::Key::Public::DSA::verify;
1;

View File

@@ -0,0 +1,57 @@
package Crypt::OpenPGP::Key::Secret::ElGamal;
use strict;
use Crypt::OpenPGP::Key::Public::ElGamal;
use Crypt::OpenPGP::Key::Secret;
use Crypt::OpenPGP::ErrorHandler;
use base qw( Crypt::OpenPGP::Key::Secret Crypt::OpenPGP::ErrorHandler );
sub secret_props { qw( x ) }
*public_props = \&Crypt::OpenPGP::Key::Public::ElGamal::public_props;
*crypt_props = \&Crypt::OpenPGP::Key::Public::ElGamal::crypt_props;
*size = \&Crypt::OpenPGP::Key::Public::ElGamal::size;
*keygen = \&Crypt::OpenPGP::Key::Public::ElGamal::keygen;
*can_encrypt = \&Crypt::OpenPGP::Key::Public::ElGamal::can_encrypt;
sub init {
my $key = shift;
$key->{key_data} = shift || Crypt::OpenPGP::ElGamal::Private->new;
$key;
}
sub decrypt { $_[0]->{key_data}->decrypt(@_[1..$#_]) }
package Crypt::OpenPGP::ElGamal::Private;
use strict;
use Crypt::OpenPGP::Util qw( mod_exp mod_inverse );
use Math::BigInt;
sub new { bless {}, $_[0] }
sub decrypt {
my $key = shift;
my($C) = @_;
my $p = $key->p;
my $t1 = mod_exp($C->{a}, $key->x, $p);
$t1 = mod_inverse($t1, $p);
my $n = Math::BigInt->new($C->{b} * $t1);
$n->bmod($p);
return $n;
}
sub _getset {
my $e = shift;
sub {
my $key = shift;
$key->{$e} = shift if @_;
$key->{$e};
}
}
*p = _getset('p');
*g = _getset('g');
*y = _getset('y');
*x = _getset('x');
1;

View File

@@ -0,0 +1,49 @@
package Crypt::OpenPGP::Key::Secret::RSA;
use strict;
use Crypt::RSA::Key::Private;
use Crypt::OpenPGP::Key::Public::RSA;
use Crypt::OpenPGP::Key::Secret;
use Crypt::OpenPGP::Util qw( bin2mp );
use Crypt::OpenPGP::ErrorHandler;
use base qw( Crypt::OpenPGP::Key::Secret Crypt::OpenPGP::ErrorHandler );
sub secret_props { qw( d p q u ) }
*sig_props = \&Crypt::OpenPGP::Key::Public::RSA::sig_props;
*public_props = \&Crypt::OpenPGP::Key::Public::RSA::public_props;
*crypt_props = \&Crypt::OpenPGP::Key::Public::RSA::crypt_props;
*size = \&Crypt::OpenPGP::Key::Public::RSA::size;
*encode = \&Crypt::OpenPGP::Key::Public::RSA::encode;
*keygen = \&Crypt::OpenPGP::Key::Public::RSA::keygen;
*can_encrypt = \&Crypt::OpenPGP::Key::Public::RSA::can_encrypt;
*can_sign = \&Crypt::OpenPGP::Key::Public::RSA::can_sign;
sub init {
my $key = shift;
$key->{key_data} = shift ||
Crypt::RSA::Key::Private->new( Password => 'pgp' );
$key;
}
*encrypt = \&Crypt::OpenPGP::Key::Public::RSA::encrypt;
sub decrypt {
my $key = shift;
my($C) = @_;
require Crypt::RSA::Primitives;
my $prim = Crypt::RSA::Primitives->new;
$prim->core_decrypt( Key => $key->{key_data}, Cyphertext => $C->{c} );
}
sub sign {
my $key = shift;
my($dgst, $hash_alg) = @_;
my $m = encode($dgst, $hash_alg, $key->bytesize - 1);
require Crypt::RSA::Primitives;
my $prim = Crypt::RSA::Primitives->new;
$m = bin2mp($m);
my $c = $prim->core_sign( Key => $key->{key_data}, Message => $m );
{ c => $c }
}
1;