I've been automating a login that encrypts the password on the client with the WebCrypto API before it is sent out.
Specifically, it's using RSA-OAEP and basically follows the examples from the MDN github:
let key = window.crypto.subtle.importKey(
"spki", binaryDer,
{ name: "RSA-OAEP", hash: "SHA-256" },
true, ["encrypt"]
);
let ciphertext = window.crypto.subtle.encrypt(
{ name: "RSA-OAEP" },
key, cleartext
);
I would have liked to do this in perl, but Crypt::OpenSSL::RSA
only supports
EME-OAEP padding as defined in PKCS #1 v2.0 with SHA-1, MGF1
...and I neither see a way to change the hash function for the padding, nor did I find another module for the job.
So I had to resort to calling the openssl
binary and encrypt the password like so:
openssl pkeyutl -in cleartext.txt -encrypt -pubin -inkey key.pem \
-pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256 \
-pkeyopt rsa_mgf1_md:sha256
This works, however I was wondering if there is a way to achieve this with perl only.
Since Shawn hasn't responded, I'm answering this myself.
His suggestion to use Crypt::PK::RSA was spot on. This library is absolutely fantastic: It supports the wanted algorithmic variants, has no dependencies at all and covers a huge array of cryptographic methods. Highly recommended.
For the use case outlined in my question; this is how to implement it:
use strict;
use Crypt::PK::RSA;
use MIME::Base64;
my $pubkey = <<EOKEY;
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDHlYKg9DeHB3/dY1D9WCyJTnl5
vEzAXpUOL9tDtdPUl96brIbbdMLooO1hKjsq98kLs1q4vOn/pxvzk0BRwhiu7Vvb
VUjAn/2HHDDL0U1utqqlMJhaffeLI3HEq5o/lSMFY7sSkZU/E4YX1yqAN0SE7xfK
B2uzcNq60sMIfp6siQIDAQAB
-----END PUBLIC KEY-----
EOKEY
my $pk = Crypt::PK::RSA->new(\$pubkey);
my $cleartext = 'pAsSwOrD';
my $ciphertext = encode_base64( $pk->encrypt($cleartext, 'oaep', 'SHA256', ''), '' );
print $ciphertext."\n";