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   1786594 use strict;
  18         32  
  18         593  
4 18     18   102 use warnings;
  18         35  
  18         976  
5              
6 18     18   97 use Carp; # Removing carp will break the XS code.
  18         75  
  18         1097  
7 18     18   7960 use Crypt::OpenSSL::Bignum;
  18         22536  
  18         873  
8              
9             our $VERSION = '0.41';
10              
11 18     18   120 use XSLoader;
  18         34  
  18         923  
12             XSLoader::load 'Crypt::OpenSSL::RSA', $VERSION;
13              
14             BEGIN {
15 18     18   40 eval {
16 18         56 local $SIG{__DIE__}; # prevent outer handlers from being called
17 18         12947 require Crypt::OpenSSL::Bignum;
18             };
19             } ## no critic qw(RequireCheckingReturnValueOfEval);
20              
21             sub new_public_key {
22 30     30 1 6615364 my ( $proto, $p_key_string ) = @_;
23 30 100 66     470 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       245 if ( $p_key_string =~ /^-----BEGIN RSA PUBLIC KEY-----/ ) {
    100          
    100          
    100          
27 14         15733 return $proto->_new_public_key_pkcs1($p_key_string);
28             }
29             elsif ( $p_key_string =~ /^-----BEGIN PUBLIC KEY-----/ ) {
30 6         6478 return $proto->_new_public_key_x509($p_key_string);
31             }
32             elsif ( $p_key_string =~ /^-----/ ) {
33 3         473 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       13 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         1178 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         1032 return $proto->_new_public_key_pkcs1_der($p_key_string);
48             }
49             }
50             else {
51 3         369 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 2033265 my ( $proto, $p_key_string, @rest ) = @_;
58 33 100 100     488 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       239 if ( $p_key_string =~ /^-----/ ) {
    100          
62 24         40080 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         12219 return $proto->_new_private_key_der($p_key_string, @rest);
67             }
68             else {
69 3         780 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 176278 my ( $proto, $n, $e, $d, $p, $q, %opts ) = @_;
76 18 100       46 my $rsa = $proto->_new_key_from_parameters( map { $_ ? $_->pointer_copy() : 0 } $n, $e, $d, $p, $q );
  90         616894  
77 15 100 66     138 if ( $opts{check} && $rsa && $rsa->is_private() ) {
      100        
78 1 50       55 $rsa->check_key()
79             or croak("RSA key check failed: inconsistent key parameters");
80             }
81 15         113 return $rsa;
82             }
83              
84             sub import_random_seed {
85 13     13 1 2382307 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 1321987 return map { $_ ? Crypt::OpenSSL::Bignum->bless_pointer($_) : undef } shift->_get_key_parameters();
  128         316  
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   253 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__