Zippy1970 has asked for the wisdom of the Perl Monks concerning the following question:

Hi, First of all, I'm very new to OpenSSL (not so new to Perl) so if I do nooby stuff it's because I am. ;) I'm currently trying to implement iDEAL (an online payment method developed by banks) for a website and I'm trying to do it in Perl (which is my preferred choice of programming language). Now all publicly available code (and APIs) for this is in PHP. So far I haven't found a single line of code for Perl. Anyway, one of the things I need to do is sign XML. For this purpose I need to create a private/public key pair like this:
 openssl genrsa -aes128 -out priv.pem -passout pass:[privatePassKey] 2048

 openssl req -x509 -sha256 -new -key priv.pem -passin pass:[privatePassKey] -days 1825 -out cert.cer
As said, I need to sign XML using my private key. I do that as follows:
  use Crypt::OpenSSL::RSA;

  my $key_string = _SlurpFile( "priv.pem" );
  my $rsa_priv = Crypt::OpenSSL::RSA->new_private_key( $key_string );
  $rsa_priv->use_pkcs1_padding();
  $rsa_priv->use_sha256_hash();
  my $signature = $rsa_priv->sign( $XMLToSign );
The problem is that this generates the following error
  RSA.xs:178: OpenSSL error: unsupported encryption at test.pl line 160.
and line 160 being
  my $rsa_priv = Crypt::OpenSSL::RSA->new_private_key( $key_string );
After some searching, I found out that I could get rid of this error by including this:
  use Net::SSLeay;
  Net::SSLeay::OpenSSL_add_all_algorithms();
Now I no longer get the error but when I run the code, it now prompts me with this:
  Enter PEM pass phrase:
Since this is going to be an unattended cgi script, I want it to use my privatePassKey automatically, obviously. So is there another way to get rid of the (unsupported encryption) error? If not, is there a way I can get it to accept a password automatically?

Replies are listed 'Best First'.
Re: AES support for Crypt::OpenSSL::RSA?
by Anonymous Monk on Feb 04, 2014 at 05:31 UTC

    Consider using Crypt::PK::RSA which supports import of encrypted RSA keys in PEM format.

    use Crypt::PK::RSA; my $pkrsa = Crypt::PK::RSA->new("priv.pem", $password); my $data = 'any data you want to sign'; my $signature = $pkrsa->sign_message($data, "SHA256", "v1.5");

    It seems to interoperate well with openssl.

      Awesome! That worked perfectly!
      (stoopid question deleted)
Re: AES support for Crypt::OpenSSL::RSA?
by kschwab (Vicar) on Feb 04, 2014 at 04:10 UTC
    I think that Convert::PEM can do what you're looking for. See the code snippet below borrowed from stuff-things.net Use the return value from decryptPEM($file,$password); as the value of your $key_string variable in your code.
    # # borrowed from # http://stuff-things.net # use Convert::PEM; sub decryptPEM { my ($file,$password) = @_; my $pem = Convert::PEM->new( Name => 'RSA PRIVATE KEY', ASN => qq( RSAPrivateKey SEQUENCE { version INTEGER, n INTEGER, e INTEGER, d INTEGER, p INTEGER, q INTEGER, dp INTEGER, dq INTEGER, iqmp INTEGER } )); my $pkey = $pem->read(Filename => $file, Password => $password); return(undef) unless ($pkey); # Decrypt failed. $pem->encode(Content => $pkey); }

      Re: Convert::PEM

      I had found that code too but for some reason it always returned undef (Decrypt failed).

Re: AES support for Crypt::OpenSSL::RSA?
by Mr. Muskrat (Canon) on Feb 05, 2014 at 21:26 UTC
      I've downloaded all sample iDEAL code I could find. None worked. They were either for the old iDEAL version or they simply did not work. I don't understand what I'm doing wrong. According to every single piece of documentation I've read about iDEAL and signing XML, it should work yet iDEAL keeps returning "invalid digital signature". This is what I do:
      # $digest contains the digest of the message (confirmed to be correct)
      
      my $SignedInfo = <<EOT;
          <SignedInfo>
            <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
            <SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" />
            <Reference URI="">
              <Transforms>
                <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
              </Transforms>
              <DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
              <DigestValue>$digest</DigestValue>
            </Reference>
          </SignedInfo>
      EOT
      
      # SignedInfo needs to be signed using RSAWithSHA256
      
      my $dataToSign = _CanonicalizeXML( $signedInfo, 1 ); # Does exclusive canonicalization
      my $pkrsa      = Crypt::PK::RSA->new( "priv.pem", $password );
      my $sig        = $pkrsa->sign_message( $dataToSign, "SHA256", "v1.5" );
      
      $sig = encode_base64( $sig );
      chomp( $sig );
      
      .
      . I then continue building the XML message.
      .
      
      sub _CanonicalizeXML {
        my ($xml, $exclusive) = @_;
      
        my $xpath = '<XPath>(//. | //@* | //namespace::*)</XPath>';
        return XML::CanonicalizeXML::canonicalize( $xml, $xpath, [], $exclusive, 0 );
      }
      
      
      When I send the XML message to the iDEAL server, it returns "invalid digital signture"...