I wrote this for PK auth in Hybrid IRCD. Mostly because I didn't want to have to compile the challenge binary on computers.
#!/usr/bin/perl
use strict;
use warnings;
use Crypt::OpenSSL::RSA;
my $private_file = shift or die "First arg is private file";
my $private_string = do {
open my $private_fh, '<', $private_file or die "Couldn't open $private_file: $!";
local $/;
<$private_fh>;
};
my $private_key = Crypt::OpenSSL::RSA->new_private_key($private_string);
$private_key->check_key() or die;
$private_key->use_pkcs1_padding;
my $challenge = shift;
my $binary_challenge = pack("H*", $challenge);
my $binary_response = $private_key->decrypt($binary_challenge);
print unpack("H*", $binary_response) . "\n";
Reading the challenge from the argument list is probably bad form, but I don't care at the moment.