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

Hello all! I ask you to help me understand what I am doing wrong.

I created two scripts:

RSA_encrypt_test.pl - encryption of plain text "Hello!!!" in the file "puzzle"

RSA_decrypt_test.pl - decryption of the ciphertext in the file "puzzle.encrypt"

I provide both scripts below.

#! /usr/bin/perl # RSA_encrypt_test.pl use strict; use Crypt::OpenSSL::Bignum; use Crypt::OpenSSL::Random; use Crypt::OpenSSL::RSA; use Data::Dumper ; my $param_ref = { n => 'B99C5E09B0B215A4F65D34F4AF763F254D1094C1356951F40A6EDCBB5779 +A540C1EA363568002F7331A71085D3207C68B5B51C9F010272186261A181D65A80E9' +, e => '10001', d => 'EC8AD0EDFFEFCD443D2C6023FEB37789137D65B18ADEC333F1200FF2CC15 +800C7C2FFA92AE70077DA2C4C6F1C3795EA00087E4E97A5BCF5CEAEDD1567841C46E' }; my $n = Crypt::OpenSSL::Bignum->new_from_hex($param_ref->{n}); my $e = Crypt::OpenSSL::Bignum->new_from_hex($param_ref->{e}); my $d = Crypt::OpenSSL::Bignum->new_from_hex($param_ref->{d}); my $rsa = Crypt::OpenSSL::RSA->new_key_from_parameters($n, $e, $d); my $target = "puzzle"; open my $OUTF, '>', "$target.encrypt" or die "Error opening file $targ +et.decrypt: $!\n"; binmode $OUTF; open my $F, '<', "$target" or die "Error opening file $target: $!\n"; binmode $F; # ---------------- Checking by padding ------------------ #$rsa->use_no_padding(); #$rsa->use_pkcs1_padding(); #$rsa->use_pkcs1_oaep_padding(); #$rsa->use_sslv23_padding(); # ------------------ Checking all keys ------------------- #print $OUTF "private key is: %s\n", $rsa->get_private_key_string(); + #print $OUTF "public key is: %s\n", $rsa->get_public_key_string(); #print $OUTF "public key (in PKCS1 format) is: %s\n", $rsa->get_public +_key_string(); #print $OUTF "public key (in X509 format) is:\n", $rsa->get_public_key +_x509_string(); while (read $F, my $buffer, 8) { print $OUTF $rsa->encrypt($buffer); } close $OUTF or die "Error closing $target.decrypt: $!\n"; close $F or die "Error closing $target: $!\n";

-----------

#! /usr/bin/perl # RSA_decrypt_test.pl use strict; use Crypt::OpenSSL::Bignum; use Crypt::OpenSSL::Random; use Crypt::OpenSSL::RSA; use Data::Dumper ; my $param_ref = { n => 'B99C5E09B0B215A4F65D34F4AF763F254D1094C1356951F40A6EDCBB5779 +A540C1EA363568002F7331A71085D3207C68B5B51C9F010272186261A181D65A80E9' +, e => '10001', d => 'EC8AD0EDFFEFCD443D2C6023FEB37789137D65B18ADEC333F1200FF2CC15 +800C7C2FFA92AE70077DA2C4C6F1C3795EA00087E4E97A5BCF5CEAEDD1567841C46E' }; my $n = Crypt::OpenSSL::Bignum->new_from_hex($param_ref->{n}); my $e = Crypt::OpenSSL::Bignum->new_from_hex($param_ref->{e}); my $d = Crypt::OpenSSL::Bignum->new_from_hex($param_ref->{d}); my $rsa = Crypt::OpenSSL::RSA->new_key_from_parameters($n, $e, $d); my $target = "puzzle.encrypt"; open my $OUTF, '>', "$target.decrypt" or die "Error opening file $targ +et.decrypt: $!\n"; binmode $OUTF; open my $F, '<', "$target" or die "Error opening file $target: $!\n"; binmode $F; # ---------------- Checking by padding ------------------ $rsa->use_no_padding(); #$rsa->use_pkcs1_padding(); #$rsa->use_pkcs1_oaep_padding(); #$rsa->use_sslv23_padding(); # ------------------ Checking all keys ------------------- #print $OUTF "private key is: %s\n", $rsa->get_private_key_string(); + #print $OUTF "public key is: %s\n", $rsa->get_public_key_string(); #print $OUTF "public key (in PKCS1 format) is: %s\n", $rsa->get_public +_key_string(); #print $OUTF "public key (in X509 format) is:\n", $rsa->get_public_key +_x509_string(); while (read $F, my $buffer, 64) { #print $OUTF $rsa->public_decrypt($buffer); print $OUTF $rsa->decrypt($buffer); } close $OUTF or die "Error closing $target.decrypt: $!\n"; close $F or die "Error closing $target: $!\n";

The RSA_encrypt_test.pl script encrypts the contents of the file "puzzle" without problems and creates the file "puzzle.encrypt" But the problem is that the RSA_decrypt_test.pl script cannot decrypt back. This works without error, but no result.

I have tried various types of padding but no result.

I ask everyone who has worked with RSA to help. What's my mistake?

Replies are listed 'Best First'.
Re: RSA encrypt but no decrypt. What is the problem? (updated)
by haukex (Archbishop) on May 07, 2021 at 08:12 UTC

    It appears to be a problem* with the key you've provided. Adding die "invalid key" unless $rsa->check_key; causes the script to die. The following works for me:

    use warnings; use strict; use Crypt::OpenSSL::RSA; use Crypt::OpenSSL::Bignum; use Data::Dump; my $rsa = Crypt::OpenSSL::RSA->generate_key(1024); my $priv = $rsa->get_private_key_string; my $ciphertext = $rsa->encrypt("Hello"); my $rsa2 = Crypt::OpenSSL::RSA->new_private_key($priv); my $plaintext = $rsa2->decrypt($ciphertext); dd $plaintext; my %params; @params{qw/n e d p q/, 'd mod (p-1)', 'd mod (q-1)', '1/q mod p'} = map { $_->to_hex } $rsa->get_key_parameters; dd \%params;

    * Update: Specifically, when I replace your d and n parameters with newly generated ones, your code works for me (as long as both sides use pkcs1_padding or pkcs1_oaep_padding, the latter being the default). Note that $rsa->check_key checks for the presence of the parameters n, e, d, p, and q, you're not giving it p and q (though the decryption still works). If you were to provide Crypt::OpenSSL::RSA with only n and e, that would tell the module it's a public key only. I'm not sure why you're working with keys the way you've shown in your post?

      Yes, thanks, I have checked, your code works for me, but it is not convenient for me. In your code, encryption and decryption is done within a single script. In practice, this is not convenient. I would like one script to encrypt the message and another script to decrypt the message. In this case, it is not possible to use Crypt :: OpenSSL :: RSA-> generate_key (1024); in both scripts. The best option is to use the parameters n, e, and d.

        The best option is to use the parameters n, e, and d.

        Personally, I'd use the string representation of the keys, since that's also a standard way of sharing them, but you're free to use the parameters if you wish. My code shows examples of both.

Re: RSA encrypt but no decrypt. What is the problem?
by choroba (Cardinal) on May 07, 2021 at 08:03 UTC
    What versions of the modules do you use? I've installed all three Crypt::OpenSSL::* fresh from CPAN and running your code I'm getting
    RSA.xs:218: OpenSSL error: no inverse at decrypt.pl line 34.

    where line 34 is

    print $OUTF $rsa->decrypt($buffer);

    map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]

      First, I compile the necessary modules into the installation distribution in my account at https://platform.activestate.com/ Then I download the distribution and install it on my PC. You can see all versions in the picture: https://photos.google.com/photo/AF1QipN8rg6BB3wCq1YXo4uG_mrcVu-8U28e122W7zUv . I see that these are the latest versions.

Re: RSA encrypt but no decrypt. What is the problem?
by Anonymous Monk on May 06, 2021 at 14:14 UTC
    "... but no result?" Please add command-output to the original post, showing the terminal session for both encrypt and decrypt.

      I want to clarify the question: these scripts do not output anything to the terminal session.

      You simply run the script for execution and if there are no errors in the code, then it is executed. The first script creates an encrypted file "puzzle.encrypt" and the second script creates a decrypted file "puzzle.encrypt.decrypt" from a file "puzzle.encrypt".

        Forb, "you tell us that there is a problem." Now show us – "what, exactly, is the problem?"