Crypt-OpenSSL-RSA
view release on metacpan or search on metacpan
if ($p_check_private_encrypt) {
ok( $ciphertext = $p_rsa->private_encrypt($plaintext), "private_encrypt succeeds" );
ok( $decoded_text = $p_rsa->public_decrypt($ciphertext), "public_decrypt succeeds" );
is( $decoded_text, $plaintext, "public_decrypt(private_encrypt(plaintext)) round-trips" );
}
}
sub _Test_Sign_And_Verify {
my ( $plaintext, $rsa, $rsa_pub, $hash ) = @_;
my $sig = eval { $rsa->sign($plaintext) };
SKIP: {
skip "OpenSSL error: illegal or unsupported padding mode - $hash", 5 if $@ =~ /illegal or unsupported padding mode/i;
skip "OpenSSL error: invalid digest - $hash", 5 if $@ =~ /invalid digest|no digest set/i;
ok( $rsa_pub->verify( $plaintext, $sig ), "rsa_pub verify $hash");
my $false_sig = unpack "H*", $sig;
$false_sig =~ tr/[a-f]/[0a-d]/;
ok( !$rsa_pub->verify( $plaintext, pack( "H*", $false_sig ) ), "rsa_pub do not verify invalid $hash" );
ok( !$rsa->verify( $plaintext, pack( "H*", $false_sig ) ), "rsa do not verify invalid $hash" );
my $sig_of_other = $rsa->sign("different");
ok( !$rsa_pub->verify( $plaintext, $sig_of_other ), "rsa_pub do not verify unmatching message" );
ok( !$rsa->verify( $plaintext, $sig_of_other ), "rsa do not verify unmatching message");
}
}
sub _check_for_croak {
my ( $code, $expected ) = @_;
eval { &$code() };
like( $@, qr/$expected/, "croak matches: $expected" );
}
# On platforms without a /dev/random, we need to manually seed. In
# real life, the following would stink, but for testing purposes, it
# suffices to seed with any old thing, even if it is not actually
# random. We'll at least emulate seeding from Crypt::OpenSSL::Random,
# which is what we would have to do in "real life", since the private
# data used by the OpenSSL random library apparently does not span
# across perl XS modules.
Crypt::OpenSSL::Random::random_seed("OpenSSL needs at least 32 bytes.");
Crypt::OpenSSL::RSA->import_random_seed();
is( Crypt::OpenSSL::RSA->generate_key(512)->size() * 8, 512, "512-bit key has correct size" );
my $rsa = Crypt::OpenSSL::RSA->generate_key(2048);
is( $rsa->size() * 8, 2048, "2048-bit key has correct size" );
ok( $rsa->check_key(), "2048-bit key passes check_key()" );
$rsa->use_no_padding();
_Test_Encrypt_And_Decrypt( $rsa->size(), $rsa, 1 );
$rsa->use_pkcs1_oaep_padding();
# private_encrypt does not work with pkcs1_oaep_padding
_Test_Encrypt_And_Decrypt( $rsa->size() - 42, $rsa, 0 );
#FIXME - use_sslv23_padding seems to fail on decryption. openssl bug?
my $private_key_string = $rsa->get_private_key_string();
my $public_key_string = $rsa->get_public_key_string();
ok( $private_key_string and $public_key_string, "get_private_key_string and get_public_key_string return data" );
my $plaintext = "The quick brown fox jumped over the lazy dog";
my $rsa_priv = Crypt::OpenSSL::RSA->new_private_key($private_key_string);
is( $rsa_priv->decrypt( $rsa_priv->encrypt($plaintext) ), $plaintext, "private key round-trips encrypt/decrypt" );
my $rsa_pub = Crypt::OpenSSL::RSA->new_public_key($public_key_string);
$rsa->use_pkcs1_oaep_padding();
is( $rsa->decrypt( $rsa_pub->encrypt($plaintext) ), $plaintext, "pub encrypt + priv decrypt round-trips" );
ok( $rsa_priv->is_private(), "private key reports is_private() true" );
ok( !$rsa_pub->is_private(), "public key reports is_private() false" );
_check_for_croak(
sub { $rsa_pub->decrypt( $rsa_pub->encrypt($plaintext) ); },
"Public keys cannot decrypt"
);
_check_for_croak(
sub { $rsa_pub->check_key(); },
"Public keys cannot be checked"
);
_check_for_croak(
sub { $rsa_pub->private_encrypt("foo"); },
"Public keys cannot private_encrypt"
);
_check_for_croak(
sub { $rsa_pub->sign("foo"); },
"Public keys cannot sign messages"
);
$plaintext .= $plaintext x 5;
my @paddings = qw/pkcs1 pkcs1_oaep pkcs1_pss/;
foreach my $padding (@paddings) {
my $p = "use_${padding}_padding";
$rsa->$p;
$rsa_pub->$p;
# check signature algorithms
$rsa->use_md5_hash();
$rsa_pub->use_md5_hash();
_Test_Sign_And_Verify( $plaintext, $rsa, $rsa_pub, "md5 with $padding padding" );
$rsa->use_sha1_hash();
$rsa_pub->use_sha1_hash();
_Test_Sign_And_Verify( $plaintext, $rsa, $rsa_pub, "sha1 with $padding padding" );
if ( UNIVERSAL::can( "Crypt::OpenSSL::RSA", "use_sha512_hash" ) ) {
$rsa->use_sha224_hash();
$rsa_pub->use_sha224_hash();
_Test_Sign_And_Verify( $plaintext, $rsa, $rsa_pub, "sha224 with $padding padding" );
$rsa->use_sha256_hash();
$rsa_pub->use_sha256_hash();
_Test_Sign_And_Verify( $plaintext, $rsa, $rsa_pub, "sha256 with $padding padding" );
$rsa->use_sha384_hash();
$rsa_pub->use_sha384_hash();
_Test_Sign_And_Verify( $plaintext, $rsa, $rsa_pub, "sha384 with $padding padding" );
$rsa->use_sha512_hash();
( run in 0.483 second using v1.01-cache-2.11-cpan-e1769b4cff6 )