File Coverage

blib/lib/Crypt/OpenSSL/RSA.pm
Criterion Covered Total %
statement 44 45 97.7
branch 25 26 96.1
condition 10 12 83.3
subroutine 12 12 100.0
pod 5 5 100.0
total 96 100 96.0


line stmt bran cond sub pod time code
1             package Crypt::OpenSSL::RSA;
2              
3 18     18   1552100 use strict;
  18         31  
  18         569  
4 18     18   73 use warnings;
  18         33  
  18         949  
5              
6 18     18   79 use Carp; # Removing carp will break the XS code.
  18         48  
  18         972  
7 18     18   7453 use Crypt::OpenSSL::Bignum;
  18         21227  
  18         859  
8              
9             our $VERSION = '0.39';
10              
11 18     18   110 use XSLoader;
  18         23  
  18         947  
12             XSLoader::load 'Crypt::OpenSSL::RSA', $VERSION;
13              
14             BEGIN {
15 18     18   41 eval {
16 18         62 local $SIG{__DIE__}; # prevent outer handlers from being called
17 18         12608 require Crypt::OpenSSL::Bignum;
18             };
19             } ## no critic qw(RequireCheckingReturnValueOfEval);
20              
21             sub new_public_key {
22 30     30 1 4608532 my ( $proto, $p_key_string ) = @_;
23 30 100 66     387 croak "unrecognized key format: expected PEM-encoded key (starting with '-----BEGIN') "
24             . "or DER-encoded key (binary ASN.1 data)"
25             unless defined $p_key_string && length($p_key_string) > 0;
26 29 100       254 if ( $p_key_string =~ /^-----BEGIN RSA PUBLIC KEY-----/ ) {
    100          
    100          
    100          
27 14         14504 return $proto->_new_public_key_pkcs1($p_key_string);
28             }
29             elsif ( $p_key_string =~ /^-----BEGIN PUBLIC KEY-----/ ) {
30 6         6595 return $proto->_new_public_key_x509($p_key_string);
31             }
32             elsif ( $p_key_string =~ /^-----/ ) {
33 3         380 croak "unrecognized key format: PEM header not recognized as RSA public key. "
34             . "Expected '-----BEGIN RSA PUBLIC KEY-----' (PKCS#1) or "
35             . "'-----BEGIN PUBLIC KEY-----' (X.509)";
36             }
37             elsif ( substr($p_key_string, 0, 1) eq "\x30" ) {
38             # ASN.1 SEQUENCE tag detected — likely DER-encoded key.
39             # Search for the RSA OID (1.2.840.113549.1.1.1) in raw binary to distinguish
40             # X.509 SubjectPublicKeyInfo from PKCS#1 RSAPublicKey.
41 3 100       8 if (index($p_key_string, "\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01") >= 0) {
42             # RSA encryption OID found — X.509 SubjectPublicKeyInfo
43 1         755 return $proto->_new_public_key_x509_der($p_key_string);
44             }
45             else {
46             # No OID — assume PKCS#1 RSAPublicKey, let OpenSSL reject invalid data
47 2         604 return $proto->_new_public_key_pkcs1_der($p_key_string);
48             }
49             }
50             else {
51 3         277 croak "unrecognized key format: expected PEM-encoded key (starting with '-----BEGIN') "
52             . "or DER-encoded key (binary ASN.1 data)";
53             }
54             }
55              
56             sub new_private_key {
57 33     33 1 2032041 my ( $proto, $p_key_string, @rest ) = @_;
58 33 100 100     446 croak "unrecognized key format: expected PEM-encoded key (starting with '-----BEGIN') "
59             . "or DER-encoded key (binary ASN.1 data)"
60             unless defined $p_key_string && length($p_key_string) > 0;
61 31 100       167 if ( $p_key_string =~ /^-----/ ) {
    100          
62 24         32561 return $proto->_new_private_key_pem($p_key_string, @rest);
63             }
64             elsif ( substr($p_key_string, 0, 1) eq "\x30" ) {
65             # ASN.1 SEQUENCE tag detected — likely DER-encoded private key.
66 4         5825 return $proto->_new_private_key_der($p_key_string, @rest);
67             }
68             else {
69 3         589 croak "unrecognized key format: expected PEM-encoded key (starting with '-----BEGIN') "
70             . "or DER-encoded key (binary ASN.1 data)";
71             }
72             }
73              
74             sub new_key_from_parameters {
75 18     18 1 165486 my ( $proto, $n, $e, $d, $p, $q, %opts ) = @_;
76 18 100       56 my $rsa = $proto->_new_key_from_parameters( map { $_ ? $_->pointer_copy() : 0 } $n, $e, $d, $p, $q );
  90         440212  
77 15 100 66     125 if ( $opts{check} && $rsa && $rsa->is_private() ) {
      100        
78 1 50       49 $rsa->check_key()
79             or croak("RSA key check failed: inconsistent key parameters");
80             }
81 15         121 return $rsa;
82             }
83              
84             sub import_random_seed {
85 13     13 1 2285680 until ( _random_status() ) {
86 0         0 _random_seed( Crypt::OpenSSL::Random::random_bytes(20) );
87             }
88             }
89              
90             sub get_key_parameters {
91 16 100   16 1 1253483 return map { $_ ? Crypt::OpenSSL::Bignum->bless_pointer($_) : undef } shift->_get_key_parameters();
  128         381  
92             }
93              
94             *get_public_key_pkcs1_string = \&get_public_key_string;
95              
96             unless ( defined &use_sslv23_padding ) {
97             *use_sslv23_padding = sub {
98 1     1   258 croak( "use_sslv23_padding is not available: "
99             . "SSLv23 padding was removed in OpenSSL 3.x. "
100             . "Use use_pkcs1_oaep_padding() for encryption "
101             . "or use_pkcs1_pss_padding() for signatures instead." );
102             };
103             }
104              
105             1;
106              
107             __END__