Alt-Crypt-RSA-BigInt
view release on metacpan or search on metacpan
lib/Crypt/RSA/Key.pm view on Meta::CPAN
package Crypt::RSA::Key;
use strict;
use warnings;
## Crypt::RSA::Keys
##
## Copyright (c) 2001, Vipul Ved Prakash. All rights reserved.
## This code is free software; you can redistribute it and/or modify
## it under the same terms as Perl itself.
use base 'Class::Loader';
use base 'Crypt::RSA::Errorhandler';
use Math::Prime::Util qw(random_nbit_prime miller_rabin_random is_frobenius_khashin_pseudoprime);
use Crypt::RSA::DataFormat qw(bitsize);
use Math::BigInt try => 'GMP, Pari';
use Crypt::RSA::Key::Private;
use Crypt::RSA::Key::Public;
use Carp;
$Crypt::RSA::Key::VERSION = '1.99';
my %MODMAP = (
Native_PKF => { Module => "Crypt::RSA::Key::Public" },
Native_SKF => { Module => "Crypt::RSA::Key::Private" },
SSH_PKF => { Module => "Crypt::RSA::Key::Public::SSH" },
SSH_SKF => { Module => "Crypt::RSA::Key::Private::SSH" },
);
sub new {
my $class = shift;
my $self = {};
bless $self, $class;
$self->_storemap ( %MODMAP );
return $self;
}
sub generate {
my ($self, %params) = @_;
my $key;
unless ($params{q} && $params{p} && $params{e}) {
return $self->error ("Missing argument.") unless $params{Size};
return $self->error ("Keysize too small.") if
$params{Size} < 48;
return $self->error ("Odd keysize.") if
$params{Size} % 2;
my $size = int($params{Size}/2);
my $verbosity = $params{Verbosity} || 0;
# Switch from Maurer prime to nbit prime, then add some more primality
# testing. This is faster and gives us a wider set of possible primes.
# We really ought to consider the distribution. See:
# https://crocs.fi.muni.cz/_media/public/papers/usenixsec16_1mrsakeys_trfimu_201603.pdf
# for comments on p/q selection.
while (1) {
my $p = random_nbit_prime($size);
my $q = random_nbit_prime($size);
$p = Math::BigInt->new("$p") unless ref($p) eq 'Math::BigInt';
$q = Math::BigInt->new("$q") unless ref($q) eq 'Math::BigInt';
# For unbiased rejection sampling, generate both p/q if size too small.
next unless bitsize($p * $q) == $params{Size};
# Verify primes aren't too close together.
if ($params{Size} >= 256) {
my $threshold = Math::BigInt->new(2)->bpow($params{Size}/2 - 100);
my $diff = $p->copy->bsub($q)->babs;
next if $diff <= $threshold;
}
# We could check p-1 and q-1 smoothness.
# p and q have passed the strong BPSW test, so it would be shocking
# if they were not prime. We'll add a few more tests because they're
# cheap and we want to be extra careful, but also don't want to spend
# the time doing a full primality proof.
do { carp "$p passes BPSW but fails Frobenius test!"; next; }
unless is_frobenius_khashin_pseudoprime($p);
do { carp "$q passes BPSW but fails Frobenius test!"; next; }
unless is_frobenius_khashin_pseudoprime($q);
do { carp "$p fails Miller-Rabin testing!"; next; }
unless miller_rabin_random($p,3);
do { carp "$q fails Miller-Rabin testing!"; next; }
unless miller_rabin_random($q,3);
$key = { p => $p, q => $q, e => Math::BigInt->new(65537) };
last;
}
}
if ($params{KF}) {
$params{PKF} = { Name => "$params{KF}_PKF" };
$params{SKF} = { Name => "$params{KF}_SKF" }
}
my $pubload = $params{PKF} ? $params{PKF} : { Name => "Native_PKF" };
my $priload = $params{SKF} ? $params{SKF} : { Name => "Native_SKF" };
my $pubkey = $self->_load (%$pubload) ||
return $self->error ("Couldn't load the public key module: $@");
my $prikey = $self->_load ((%$priload), Args => ['Cipher' => $params{Cipher}, 'Password' => $params{Password} ]) ||
return $self->error ("Couldn't load the private key module: $@");
$pubkey->Identity ($params{Identity});
$prikey->Identity ($params{Identity});
$pubkey->e ($$key{e} || $params{e});
$prikey->e ($$key{e} || $params{e});
$prikey->p ($$key{p} || $params{p});
$prikey->q ($$key{q} || $params{q});
( run in 0.824 second using v1.01-cache-2.11-cpan-39bf76dae61 )