I'm trying to port the following php functionality over to perl:
public function loadKey($mod, $exp, $type = 'public')
{
$rsa = new Crypt_RSA();
$rsa->signatureMode = CRYPT_RSA_SIGNATURE_PKCS1;
$rsa->setHash('sha256');
$rsa->modulus = new Math_BigInteger(Magicsig::base64_url_decode($mod), 256);
$rsa->k = strlen($rsa->modulus->toBytes());
$rsa->exponent = new Math_BigInteger(Magicsig::base64_url_decode($exp), 256);
// snip...
}
I need to convert a string in the form ("RSA.$mod.$exp.$private_exp"):
RSA.mVgY8RN6URBTstndvmUUPb4UZTdwvwmddSKE5z_jvKUEK6yk1u3rrC9yN8k6FilGj9K0eeUPe2hf4Pj-5CmHww==.AQAB.Lgy_yL3hsLBngkFdDw1Jy9TmSRMiH6yihYetQ8jy-jZXdsZXd8V5ub3kuBHHk4M39i3TduIkcrjcsiWQb77D8Q==
...to a Crypt::RSA object. I've split out the components so I have $mod, $exp, and $private_exp, but the perl Crypt::RSA API doesn't seem to have a way to explicitly set.
Worked out on IRC, documenting it here for the rest of the world: it's completely undocumented but Crypt::RSA::Key
does have methods called n
, e
, and d
that correspond to the modulus, the public exponent, and the private exponent. Modulo bugs in the check function (which is supposed to work if p
and q
are unavailable but n
is, but actually doesn't), it's possible to create a working key with those methods.
We solved the problem together by creating a subclass of Crypt::RSA::Key::Private
with a factory method that decodes the base64 encoding (using MIME::Base64::URLSafe) and the additional binary encoding (using Math::BigInt->from_hex and unpack "H*"
) and then sets those three private members, and the Crypt::RSA
modules were able to accept it as a Key.