sebastiannielsen has asked for the wisdom of the Perl Monks concerning the following question:

How can I in perl, efficiently (fast) generate a RSA keypair, with custom random data? The function should be like that, if you supply the same random data over, and over and over again, it should generate the same keypair over and over and over again. I tried with this:
#!/usr/bin/perl use CGI ':standard'; use Digest::SHA qw(sha512); use Crypt::OpenSSL::Random; use Crypt::OpenSSL::RSA; $passphrase = param('genpass'); $prngdata = ""; print "Content-Type: text/html\n\n"; if ($passphrase) { Crypt::OpenSSL::Random::random_seed(&genrsarandom(1024)); Crypt::OpenSSL::RSA->import_random_seed(); $rsa = Crypt::OpenSSL::RSA->generate_key(1024); print "PRNG data length: ". length($prngdata)."<br>"; print "PRNG data in hex: " . uc(unpack("H*", $prngdata)) . "<br><br>"; $pubkey = $rsa->get_public_key_string(); $privkey = $rsa->get_private_key_string(); $pubkey =~ s/\n/<br>/sgi; $privkey =~ s/\n/<br>/sgi; print "Public key: <br>" . $pubkey . "<br><br>"; print "Private key: <br>" . $privkey; } else { print "<form action=\"RSAgen.cgi\">PassPhrase: <input type=\"text\" na +me=\"genpass\"><input type=\"submit\" value=\"genrsa\"></form>"; } #################################################### # CSPRNG BASED ON A PASSWORD # RETURNS SAME RANDOM DATA UPON SUPPLYING # THE SAME PASSWORD #################################################### sub genrsarandom() { $bytes = $_[0]; $randomdata = ""; $numberofrounds = int($bytes / 64) + 1; for ($i = 0; $i < $numberofrounds; $i++) { $randomdata = $randomdata . sha512($passphrase . sha512($i.$i)); } $randomdata = substr($randomdata, 0, $bytes); $prngdata = $randomdata; return $randomdata; }
But even if I supply the same password to the genrsarandom() function everytime (by using a global variable), the Crypt::OpenSSL::RSA function still generates different keypairs everytime. Have a look at it here:

http://www.sebn.us.to/old/RSAgen.cgi

Enter something in the textbox. It now generates a keypair, but the problem is that the keypair is different everytime, even if you supply the same password again. However, theres NO error in the genrsarandom() function since it returns the same random data everytime the same password is supplied. The system should return the same keypair everytime the same password is entered.

How can I make so the Crypt::OpenSSL::RSA in some way directly use my supplied random data for key generation?

Replies are listed 'Best First'.
Re: Generate RSA keypair in perl efficently with custom PRNG
by zwon (Abbot) on Feb 19, 2011 at 03:14 UTC

    The fact that you calling random_seed with the same data, doesn't mean that you will get the same random data. If you look onto Crypt::OpenSSL::Random documentation, it doesn't claim that with the same seed it will produce the same pseudo random sequence. This example demonstrates the opposite, every time you run it it will produce different result:

    use 5.012; use warnings; use Crypt::OpenSSL::Random; use MIME::Base64; Crypt::OpenSSL::Random::random_seed("This is not a random seed"); my $random_bytes = Crypt::OpenSSL::Random::random_bytes(20); say encode_base64($random_bytes);

    Update:

    Crypt::OpenSSL::RSA has new_key_from_parameters method, which generates keypair from the provided parameters. So the only problem you need to solve is to generate key parameters from the password. Have a look onto next_prime from Math::Primality package for generating big primes from the password.

    PS: I assume that you know what are you doing

      But isn't using Math::Primality a slow method of generating keys?

      Isn't there any way to supply own random data to a *Efficient* key generating process, that generates a keypair fast and efficiently?

      I tried with a another key generating process but it took about 1 minute to generate a 256 bit RSA keypair. Thats too slow. I need a fast and efficient method.

        You can use also Math::GMPz, which uses GMP library:

        use 5.012; use warnings; use Math::GMPz qw(:mpz ); use Digest::SHA qw(sha512_hex); my $sha = sha512_hex('password'); my $op = Rmpz_init_set_str($sha, 16); my $rop = Rmpz_init2(512); Rmpz_nextprime($rop, $op); say Rmpz_get_str($rop, 16);
        it takes less than a second on my notebook.