sub
_asn1 {
return
Crypt::Perl::ASN1->new()->prepare(
Crypt::Perl::RSA::Template::get_template(
'INTEGER'
),
);
}
sub
private {
my
(
$pem_or_der
) =
@_
;
_ensure_der(
$pem_or_der
);
my
$key_obj
;
try
{
my
$parsed
= _decode_rsa(
$pem_or_der
);
$key_obj
= _new_private(
$parsed
);
}
catch
{
my
$rsa_err
=
$_
;
try
{
$key_obj
= private_pkcs8(
$pem_or_der
);
}
catch
{
die
Crypt::Perl::X::create(
'Generic'
,
"Failed to parse as either RSA ($rsa_err) or PKCS8 ($_)"
);
};
};
return
$key_obj
;
}
sub
private_pkcs8 {
my
(
$pem_or_der
) =
@_
;
_ensure_der(
$pem_or_der
);
my
$pkcs8
= _decode_pkcs8(
$pem_or_der
);
my
$parsed
= _decode_rsa_within_pkcs8_or_die(
$pkcs8
);
return
_new_private(
$parsed
);
}
sub
public {
my
(
$pem_or_der
) =
@_
;
_ensure_der(
$pem_or_der
);
my
$key_obj
;
try
{
my
$parsed
= _decode_rsa_public(
$pem_or_der
);
$key_obj
= _new_public(
$parsed
);
}
catch
{
my
$rsa_err
=
$_
;
try
{
$key_obj
= public_SPKI(
$pem_or_der
);
}
catch
{
die
Crypt::Perl::X::create(
'Generic'
,
"Failed to parse as either RSA ($rsa_err) or SubjectPublicKeyInfo ($_)"
);
};
};
return
$key_obj
;
}
sub
public_SPKI {
my
(
$pem_or_der
) =
@_
;
_ensure_der(
$pem_or_der
);
my
$spki
= _decode_spki(
$pem_or_der
);
my
$parsed
= _decode_rsa_public_within_spki_or_die(
$spki
);
return
_new_public(
$parsed
);
}
my
%JTK_TO_NEW
=
qw(
n modulus
e publicExponent
d privateExponent
p prime1
q prime2
dp exponent1
dq exponent2
qi coefficient
)
;
sub
jwk {
my
(
$hr
) =
@_
;
my
%constr_args
;
for
my
$k
(
keys
%$hr
) {
next
if
!
$JTK_TO_NEW
{
$k
};
$constr_args
{
$JTK_TO_NEW
{
$k
} } = Crypt::Perl::JWK::jwk_num_to_bigint(
$hr
->{
$k
});
}
if
(
$hr
->{
'd'
}) {
$constr_args
{
'version'
} = 0;
return
Crypt::Perl::RSA::PrivateKey->new( \
%constr_args
);
}
return
Crypt::Perl::RSA::PublicKey->new( \
%constr_args
);
}
sub
_decode_macro {
my
(
$der_r
,
$macro
) = ( \
$_
[0],
$_
[1] );
my
$parser
= _asn1()->find(
$macro
);
return
$parser
->decode(
$$der_r
);
}
sub
_decode_rsa {
my
(
$der_r
) = (\
$_
[0]);
return
_decode_macro(
$$der_r
,
'RSAPrivateKey'
);
}
sub
_decode_rsa_public {
my
(
$der_r
) = (\
$_
[0]);
return
_decode_macro(
$$der_r
,
'RSAPublicKey'
);
}
sub
_decode_rsa_within_pkcs8_or_die {
my
(
$pkcs8_hr
) =
@_
;
my
$dec
;
try
{
$dec
= _decode_rsa(
$pkcs8_hr
->{
'privateKey'
} );
}
catch
{
die
Crypt::Perl::X::create(
'Generic'
,
"Failed to parse RSA within PKCS8: $_"
);
};
return
$dec
;
}
sub
_decode_rsa_public_within_spki_or_die {
my
(
$spki_hr
) =
@_
;
my
$dec
;
try
{
$dec
= _decode_rsa_public(
$spki_hr
->{
'subjectPublicKey'
}[0] );
}
catch
{
die
Crypt::Perl::X::create(
'Generic'
,
"Failed to parse RSA within SubjectPublicKeyInfo: $_"
);
};
return
$dec
;
}
sub
_decode_pkcs8 {
my
(
$der_r
) = (\
$_
[0]);
return
_decode_macro(
$$der_r
,
'PrivateKeyInfo'
);
}
sub
_decode_spki {
my
(
$der_r
) = (\
$_
[0]);
return
_decode_macro(
$$der_r
,
'SubjectPublicKeyInfo'
);
}
sub
_new_public {
my
(
$parsed_hr
) =
@_
;
return
Crypt::Perl::RSA::PublicKey->new(
$parsed_hr
);
}
sub
_new_private {
my
(
$parsed_hr
) =
@_
;
return
Crypt::Perl::RSA::PrivateKey->new(
$parsed_hr
);
}
sub
_pem_to_der {
$_
[0] = Crypt::Format::pem2der(
@_
);
return
;
}
sub
_ensure_der {
my
(
$pem_or_der_r
) = \
$_
[0];
if
(
$$pem_or_der_r
=~ m<\A-> ) {
_pem_to_der(
$$pem_or_der_r
);
}
return
;
}
1;