perlencryptionopensslrsaoaep

RSA using EME-OAEP padding with SHA-256 as hash function


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.


Solution

  • 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";