Signing data using Crypt::OpenSSL::RSA in perl - perl

I am trying to sign my data using Crypt::OpenSSL::RSA in perl. This is my code
use Crypt::OpenSSL::RSA;
open $privfh, '>:encoding(UTF-8)', 'private_key';
$rsa = Crypt::OpenSSL::RSA->generate_key(1024);
$key_string=$rsa->get_private_key_string();
print $privfh $key_string;
$rsa_priv = Crypt::OpenSSL::RSA->new_private_key($key_string);
$rsa_pub = $rsa->get_public_key_string();
$plaintext="hello";
$signature = $rsa_priv->sign($plaintext);
print "Signed correctly\n" if ($rsa->verify($plaintext, $signature));
This program is running fine and i am able to sign data correctly. But the issue is that i have to sign a lot of data so i am writing key_string to a file so that i can use it again and again but the issue is when i try to use it again using following code
use Crypt::OpenSSL::RSA;
open FILE ,'<','private_key';
{
local $/;
$keystring=<FILE>;
}
print "$keystring\n";
$rsa_priv = Crypt::OpenSSL::RSA->new_private_key($key_string);
it is throwing error and not generating $rsa_priv. The error given by the program is
RSA.xs:178: OpenSSL error: no start line at testperl.pl line 11, <FILE> line 1.
What should i do so that i am able to signing again and again after generating key for one time only.

You are reading the file into a variable $keystring but initializing the private key using the variable $key_string. Change $keystring to $key_string.
Perl offers use strict; to avoid these kind of problems.
Also, if you use use warnings;, perl will also warn you about accessing unitialized variables.

Related

Deciphering File::Fetch error

I was trying to use File::Fetch in a simple script to download a file. Unfortunately, it errors out and I can't seem to find why.
use strict;
use warnings;
use File::Fetch;
my $url = 'https://ftp.mozilla.org/pub/firefox/releases/42.0b7/linux-i686/en-US/firefox-42.0b7.tar.bz2';
my $ff = File::Fetch->new(uri => $url);
my $where = $ff->fetch( to => '/tmp' ) or die $ff->error;
print "Downloaded to ".$where."\n";
At execution:
#./filefetch.pl
Use of uninitialized value in die at ./filefetch.pl line 12.
Died at ./filefetch.pl line 12.
Going into File::Fetch::fetch() with the debugger, the problem is File::Fetch failed to find a way to deal with the https scheme. It appears to have no support for https. It correctly returned false, but it did not populate its error field.
You are correct in assuming it should consider missing a scheme an error. You can report a bug here.

Open2 Api failure while installing Mead software

I am running into some issues trying to install a software called MEAD . I would appreciate if someone could have alook .
I get the following error while installing
/mead/bin # ./mead.pl GA3
Using system rc-file: /home/karosh/mead/bin/../.meadrc
Warning: Can't find user rc-file
Cluster: /home/karosh/mead/bin/../data/GA3/GA3.cluster
open2: exec of /home/karosh/mead/bin/driver.pl failed at ./mead.pl line 230
THe mead software is not written by me so I have not changed any of the perl scrips . I line 230 in the driver.pl file is
sub run_mead {
my %options = #_;
my $reader = FileHandle->new();
my $writer = FileHandle->new();
unless ( open2($reader, $writer, "$FindBin::Bin/driver.pl") ) {
die "Unable to run MEAD.\n";
}
...
...
}
Does this error mean that open2 was not found . The mead folks have put the following line in the file:
use strict;
use File::Spec;
use FileHandle;
use IPC::Open2;
Or does it mean that i need to install the rpm that contains the API . I see that this API is a part of the core perl bundle http://perldoc.perl.org/IPC/Open2.html. So why was it not installed ? Do i need to install perl again .
Someone has earlier faced this problem - http://www.summarization.com/~radev/mead/email/0160.html but the solution is not working for me . I find no Perl files with the incorrect perl directives . The mead team has been dissolved and there is no one to ask questions but I need to use this software.
I think if some one can explain me the meaning of the error than I can do deeper. Anyone?
It probably means that .../driver.pl doesn't have execute permission. Change the file permissions or call it like
open2($reader, $writer, "perl $FindBin::Bin/driver.pl")
open2($reader, $writer, "$^X $FindBin::Bin/driver.pl")

Why does my Perl CGI program fail with "Software error: ..."?

When I try to run my Perl CGI program, the returned web page tells me:
Software error: For help, please send mail to the webmaster (root#localhost), giving this error message and the time and date of the error.
Here is my code in one of the file:
#!/usr/bin/perl
use lib "/home/ecoopr/ecoopr.com/CPAN";
use CGI;
use CGI::FormBuilder;
use CGI::Session;
use CGI::Carp (fatalsToBrowser);
use CGI::Session;
use HTML::Template;
use MIME::Base64 ();
use strict;
require "./db_lib.pl";
require "./config.pl";
my $query = CGI->new;
my $url = $query->url();
my $hostname = $query->url(-base => 1);
my $login_url = $hostname . '/login.pl';
my $redir_url = $login_url . '?d=' . $url;
my $domain_name = get_domain_name();
my $helpful_msg = $query->param('m');
my $new_trusted_user_fname = $query->param('u');
my $action = $query->param('a');
$new_trusted_user_fname = MIME::Base64::decode($new_trusted_user_fname);
####### Colin: Added July 12, 2009 #######
my $view = $query->param('view');
my $offset = $query->param('offset');
####### Colin: Added July , 2009 #######
#print $session->header;
#print $new_trusted_user;
my $helpful_msg_txt = qq[];
my $helpful_msg_div = qq[];
if ($helpful_msg)
The "please send mail to the webmaster" message you see is a generic message that the web server gives you when anything goes wrong and nothing handles it. It's not at all interesting in terms of solving the actual problem. Check the error log to find possible relevant error output from your program.
And, go through my How do I troubleshoot my Perl CGI script? advice on finding the problem.
My guess is that you have a syntax error with that dangling if(). What you have posted isn't a valid Perl program.
Good luck,
is that something related to suexec module
Improper configuration of suExec can cause permission errors
The suEXEC feature provides Apache users the ability to run CGI and SSI programs under user IDs different from the user ID of the calling web server. Normally, when a CGI or SSI program executes, it runs as the same user who is running the web server.
apache recommends that you not consider using suEXEC.
http://httpd.apache.org/docs/2.2/suexec.html
From the StackOverflow page: How to trap program crashes with HTTP error code 500
I see that your include: use CGI::Carp (fatalsToBrowser);
... stifles the HTTP 500 error. Simply removing this will allow the programs to crash "properly".

Why does my Perl unit test fail in EPIC but work in the debugger?

Has anyone ever experienced a unit test that fails and when they tried to debug it to find out where the failure was occurring, the unit test succeeds when running the code in the debugger?
I'm using Eclipse 3.5.1 with EPIC 0.6.35 and ActiveState ActivePerl 5.10.0. I wrote module A and module B both with multiple routines. A routine in module B calls a bunch of routines from module A. I'm adding mock objects to my module B unit test file to try to get more complete code coverage on module B where the code in module B tests to see if all the calls to module As routines fail or succeed. So I added some mock objects to my unit test to force some of the module A routines to return failures, but I was not getting the failures as expected. When I debugged my unit test file, the calls to the module A routine did fail as expected (and my unit test succeeds). When I run the unit test file as normal without debugging, the call to the mocked Module A routine does not fail as expected (and my unit test fails).
What could be going on here? I'll try to post a working example of my problem if I can get it to fail using a small set of simple code.
ADDENDUM: I got my code whittled down to a bare minimum set that demonstrates my problem. Details and a working example of the problem follows:
My Eclipse project contains a "lib" directory with two modules ... MainModule.pm and UtilityModule.pm. My Eclipse project also contains at the top level a unit test file named MainModuleTest.t and a text file called input_file.txt which just contains some garbage text.
EclipseProject/
MainModuleTest.t
input_file.txt
lib/
MainModule.pm
UtilityModule.pm
Contents of the MainModuleTest.t file:
use Test::More qw(no_plan);
use Test::MockModule;
use MainModule qw( mainModuleRoutine );
$testName = "force the Utility Module call to fail";
# set up mock utility routine that fails
my $mocked = new Test::MockModule('UtilityModule');
$mocked->mock( 'slurpFile', undef );
# call the routine under test
my $return_value = mainModuleRoutine( 'input_file.txt' );
if ( defined($return_value) ) {
# failure; actually expected undefined return value
fail($testName);
}
else {
# this is what we expect to occur
pass($testName);
}
Contents of the MainModule.pm file:
package MainModule;
use strict;
use warnings;
use Exporter;
use base qw(Exporter);
use UtilityModule qw( slurpFile );
our #EXPORT_OK = qw( mainModuleRoutine );
sub mainModuleRoutine {
my ( $file_name ) = #_;
my $file_contents = slurpFile($file_name);
if( !defined($file_contents) ) {
# failure
print STDERR "slurpFile() encountered a problem!\n";
return;
}
print "slurpFile() was successful!\n";
return $file_contents;
}
1;
Contents of the UtilityModule.pm file:
package UtilityModule;
use strict;
use warnings;
use Exporter;
use base qw(Exporter);
our #EXPORT_OK = qw( slurpFile );
sub slurpFile {
my ( $file_name ) = #_;
my $filehandle;
my $file_contents = "";
if ( open( $filehandle, '<', $file_name ) ) {
local $/=undef;
$file_contents = <$filehandle>;
local $/='\n';
close( $filehandle );
}
else {
print STDERR "Unable to open $file_name for read: $!";
return;
}
return $file_contents;
}
1;
When I right-click on MainModuleTest.t in Eclipse and select Run As | Perl Local, it gives me the following output:
slurpFile() was successful!
not ok 1 - force the Utility Module call to fail
1..1
# Failed test 'force the Utility Module call to fail'
# at D:/Documents and Settings/[SNIP]/MainModuleTest.t line 13.
# Looks like you failed 1 test of 1.
When I right click on the same unit test file and select Debug As | Perl Local, it gives me the following output:
slurpFile() encountered a problem!
ok 1 - force the Utility Module call to fail
1..1
So, this is obviously a problem. Run As and Debug As should give the same results, right?!?!?
Both Exporter and Test::MockModule work by manipulating the symbol table. Things that do that don't always play nicely together. In this case, Test::MockModule is installing the mocked version of slurpFile into UtilityModule after Exporter has already exported it to MainModule. The alias that MainModule is using still points to the original version.
To fix it, change MainModule to use the fully qualified subroutine name:
my $file_contents = UtilityModule::slurpFile($file_name);
The reason this works in the debugger is that the debugger also uses symbol table manipulation to install hooks. Those hooks must be getting installed in the right way and at the right time to avoid the mismatch that occurs normally.
It's arguable that it's a bug (in the debugger) any time the code behaves differently there than it does when run outside the debugger, but when you have three modules all mucking with the symbol table it's not surprising that things might behave oddly.
Does your mocking manipulate the symbol table? I've seen a bug in the debugger that interferes with symbol table munging. Although in my case the problem was reversed; the code broke under the debugger but worked when run normally.

Why can't I connect to my CAS server with Perl's AuthCAS?

I'm attempting to use an existing CAS server to authenticate login for a Perl CGI web script and am using the AuthCAS Perl module (v 1.3.1). I can connect to the CAS server to get the service ticket but when I try to connect to validate the ticket my script returns with the following error from the IO::Socket::SSL module:
500 Can't connect to [CAS Server]:443 (Bad hostname '[CAS Server]')
([CAS Server] substituted for real server name)
Symptoms/Tests:
If I type the generated URL for the authentication into the web browser's location bar it returns just fine with the expected XML snippet. So it is not a bad host name.
If I generate a script without using the AuthCAS module but using the IO::Socket::SSL module directly to query the CAS server for validation on the generated service ticket the Perl script will run fine from the command line but not in the browser.
If I add the AuthCAS module into the script in item 2, the script no longer works on the command line and still doesn't work in the browser.
Here is the bare-bones script that produces the error:
#!/usr/bin/perl
use strict;
use warnings;
use CGI;
use AuthCAS;
use CGI::Carp qw( fatalsToBrowser );
my $id = $ENV{QUERY_STRING};
my $q = new CGI;
my $target = "http://localhost/cgi-bin/testCAS.cgi";
my $cas = new AuthCAS(casUrl => 'https://cas_server/cas');
if ($id eq ""){
my $login_url = $cas->getServerLoginURL($target);
printf "Location: $login_url\n\n";
exit 0;
} else {
print $q->header();
print "CAS TEST<br>\n";
## When coming back from the CAS server a ticket is provided in the QUERY_STRING
print "QUERY_STRING = " . $id . "</br>\n";
## $ST should contain the received Service Ticket
my $ST = $q->param('ticket');
my $user = $cas->validateST($target, $ST); #### This is what fails
printf "Error: %s\n", &AuthCAS::get_errors() unless (defined $user);
}
Any ideas on where the conflict might be?
The error is coming from the line directly above the snippet Cebjyre quoted namely
$ssl_socket = new IO::Socket::SSL(%ssl_options);
namely the socket creation. All of the input parameters are correct. I had edited the module to put in debug statements and print out all the parameters just before that call and they are all fine. Looks like I'm going to have to dive deeper into the IO::Socket::SSL module.
As usually happens when I post questions like this, I found the problem. It turns out the Crypt::SSLeay module was not installed or at least not up to date. Of course the error messages didn't give me any clues. Updating it and all the problems go away and things are working fine now.
Well, from the module source it looks like that IO::Socket error is coming from get_https2
[...]
unless ($ssl_socket) {
$errors = sprintf "error %s unable to connect https://%s:%s/\n",&IO::Socket::SSL::errstr,$host,$port;
return undef;
}
[...]
which is called by callCAS, which is called by validateST.
One option is to temporarily edit the module file to put some debug statements in if you can, but if I had to guess, I'd say the casUrl you are supplying isn't matching up to the _parse_url regex properly - maybe you have three slashes after the https?