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 )