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

Hello Masters of Perl!

Solved! Special thanks to sundialsvc4

The truth is that i've never touched OpenSSL before so please have this in mind if you think I seem lost when it might be very obvious.

So, I'm gonna implement an integration to a webservice. Usually web services just concatenate parameters to string which is concatenated with a secret key and then this string with be used to create an MD5-hash. In this case the signature require a bit more security, or at least more complex way of making the signature.

The signature is made up by several concatenated parameters and other parameters and then the "tricky" parts come, OpenSSL signing and verification. I've made both the public and private key from the terminal as described in the documentation for the webservice. This is how far i made it. In the documentation there is an example in which PHP is used. The methods which is used are: openssl_get_privatekey, openssl_get_publickey, openssl_sign, openssl_verify.

So, I need to find methods from a module in Perl that does the same thing as the PHP-function does.

I searched around for modules and the one I found the best documentation for was Crypt::OpenSSL::RSA.

The documentation have an example which I tested a bit before I ended up here.

I need your help to get trough this part.

Can someone here explain how I can use Crypt::OpenSSL:RSA or another module that does the same task as the four functions I mentioned above?

I need to read in the private key first, which I'm calling private.pem in the same way that PHP does it: openssl_get_privatekey(file_get_contents(private.pem)). file_get_contents just reads in the hole file to a string and returns it. I don't need help with reading in a file to a string, that's a no-brainer. But where do I go from here ?

The second part is to use a similar function to PHP:s openssl_sign.

The third part is to use a similar function to PHP:s openssl_get_publickey

And last, the forth and final step, openssl_verify.

I don't have any code that I can bring to the table due that fact I don't have anything helpful at the moment.

Best regards,
Martin

Replies are listed 'Best First'.
Re: Crypt::OpenSSL:RSA Questions
by zentara (Cardinal) on Jun 19, 2014 at 17:51 UTC

      Thanks, I'll look into it! I'm gonna read a bit more about OpenSSL in general as well. I've very little experience so that's probably a good idea.

Re: Crypt::OpenSSL:RSA Questions
by locked_user sundialsvc4 (Abbot) on Jun 19, 2014 at 19:52 UTC

    Superficially, it appears that you made an appropriate choice.   Do you have any in-progress Perl code that you could share with us?   (Or, for that matter, PHP code?)   We’ll be happy to help you with that.   (Remember to use code-tags, if it is large.)

    It appears to me that this package has a very object-oriented approach, versus PHP’s decidedly functional one.   PHP, more or less by-tradition, has a very monolithic approach to things, where you call certain functions to load information (into some “magic” but unknown location in space/time ...) so that other functions can subsequently refer to it.   This object-oriented approach is much cleaner, but it does mean that the calling sequence will be different.

    The corollary to openssl_get_privatekey(), it seems to me, would be the new_private_key() method, which is an object constructor.   (There is also a new_public_key() method, although it seems to take a string whereas PHP takes a certificate file-name.)

    Note – The Perl method-names are somewhat misleading:   you are not, say, creating a “new private key.”   Rather, you are invoking a variation of new() which takes a private-key string.   What you wind-up with, is a Perl object instance.

    Having thus successfully created a Perl object-instance which incorporates a key (using any one of the several methods provided), you would then invoke methods of that particular instance to do the various things that you need, such as signing a string or verifying a signed string.

    Unfortunately, this module author’s documentation (sic ...) is working against you.   The PerlDoc page is very ... sparse.   C’est la guerre.   Aside from the example, there seems to be no discussion of the actual methods ... merely an enumeration of the methods that exist.   Nevertheless, I think that with a very short test-script, heavily based on such examples as there are, I think that you ought to be able to muddle-through how to use this module.   And, I think that you did find the right one.

    Try constructing a minimal test-script, and feel free to post it here for peer-review.

      You sir deserve something special! I first made a php-script with the help of the example from the webservice-documentation. From this script i got end result which is useful in this case since I don't really have any clue what I'm doing :)

      The result from the PHP-script was:

      Signature: NQXhQ5mk8bNQl1BvRMJoCqp2gpyuywzfs7KRAKIFxFK4ujfJ78hCYVbrieYGgIQCQD7Wp2NZnAeZvWuws2BiP8c+4HMOIwMqIQKOBQvxhpM0q6TsPR0pkOr0IV1kLbkfzKVsXC71rGkEE4pMrIaCxJ1yVxM0cmxKh4vj9nUjYgiSAWzR76YdptHOwG99dGjXfiCTiqD7DGe8qnkW2U/DAo3F+CP+fX9DfgWxUhCr1MWk87ctbJnlxsl2C3+lJSVgpnRVJ3nJtHmWfqF/iflGUIJ4u333B1fIBzMLsY58lKyDRpT0UmCajQ9eGZNy9uKWR9ZnrkajG08tepnvEClboQ==

      This is an encoded base64 signature-string btw..

      Verify: 1

      I achived the same result with the following code:

      #!/usr/bin/perl use Crypt::OpenSSL::RSA; use MIME::Base64; Test_OpenSSL(); sub Test_OpenSSL { print "OpenSSL_Sign - Start\n"; my $signnature = OpenSSL_Sign("value1", "value2", "value3"); print "OpenSSL_Sign - Result: ".$signnature."\n"; print "OpenSSL_Sign - Done\n"; print "OpenSSL_Verify - Start\n"; my $verify = OpenSSL_Verify("value1", "value2", "value3", $signnat +ure); print "OpenSSL_Verify - Result: ".$verify."\n"; print "OpenSSL_Verify - Done\n"; } sub OpenSSL_Sign { my $param1 = $_[0]; my $param2 = $_[1]; my $param3 = $_[2]; # instead of having a function that reads the file to a string i j +ust declare a variabele with the content of the file just to make it +more clear.. my $private_key_string = qq^-----BEGIN RSA PRIVATE KEY----- MIIEpAIBAAKCAQEA1Hd90G9/IAvZleTi86cqb8ZdM6vzOsv/Fxs/OpaHYexKs+t2 rg+f/h7hiTakXvRhN1E+N1GZ2jXSCNKniqPKaamspIqGbbylBoDm353o6DULZi7N Vm/GG5+LJwZFwzTPFuH248k0sxwTjcioj0ho06yLWPvkUXiFQslHuno6g59hC5gC n9Lh89ULkSes/7BZTXtD1mVywEnvfdRIN8rH6Kbt+RlrYP+CzmENmdQ4jKEj7aYB Y3+qjsmL4D65De6OChb21i/iyhiPhdWez8+ulPRoinxMsbnWslgiWXifVueyplL8 wDDhx5yYXUwha3FYqXTSq0qk7ZsAET+ftoQ1OwIDAQABAoIBAQCu5wb9VSuzd83Q pTFnHo/Cn+sNpFmAZ3pAzT9Jva0JIXmFjyqNs3MjwMwtJnw9ZrO40/qBk30xsuiK Ns+RQ7BXN0RV12s+XvMC3Y4xO08GCNSvc4u5wh21k6r7nyBCx/BKiA20CmiFoXE/ YJXSDeuthPbZc9LKdopNJmET05bjzgkb7bK7n2bvi9hszjGp8K2RrVp/okUwX1ZP QlPTT9FMZJFRjFSh8Mt0AqfqubvCDR8fm8nzZsdgLmn4H1/1SIiA+qcJNj/J38r8 BbY8M8DIjc/xiopphc3L1BYA7B47mszbvSLcXa6B4NAxEG/rf480HnSpTqeeZ245 /KpNROsRAoGBAPq1AuRY4M1oz5gmzMpVJEO8IVFZtluIAXAjAwgd1Er0Vwt0kAqT bbiJo5nPuQT6guHzVDDOBKk9GUkKaL8e4aQ4dFnDG7APtJPjMJ1DZU32ZTtq6Ddp /kUVsHxlW6L4dfpthENGGWyYOgVsjnTGERkvJVlKksK/V4vgNAZDXzFFAoGBANjz zc9b+bUwmCReL4DPuA4UCZefXgLtNnGZvB6yh7SOjGy0eUDZFXrefcq7lnpNgkUk 43umXDcMZqw9vQkWLS5oSalFKZWgJuZGC3FakC6V0OACLOBtuKFKpmfkVJCZR2tW s68T9GzOqdh3eKWiDB91idhWq91MNbV/M/Ne0fR/AoGAQTg/tVmtuaIPhzxowCYg FgLmA/y7pNofzaU+D6l65bjkwBUlt6qcu4oK5mOUdUgaLl+Xwk6GBeTgJBEyKK4G 8yrAke1g0Y90YZiTuAWlX/++XBO2r1vCiwRWcjYH/cB3KJu+8aVVzdtYFLsl4Bj6 r7uFEtKElWcjhj7gKdTy+aUCgYBj2ChCoxCTm46ZRiNUg8Qv7nbPqc9pR2RD+b2C 3yTnKqdjq9cVyhJBnr2DnLtPA/bM/YIXuOM9jl5+LFegI+2dKu+jkCnoK3Fbjqbb fxNV7SrYvQeMLdLHoARfUcy9U11z/83n6CYYITA3aBxFFgPAQqaywoiL6vPY2Ha/ LUcw3wKBgQD5rd6CcJJxMJ46LoULYcsK69rgnEO5nivYDUiRvrlBkml0aRf8nF4x GGlIoweMgIbuH/Hvo0vt2+C7pntpR1EqAhSREcpbjGcl8eMhhQptK64arfZ9oebp 95scD2p0VbYkkxtto0gej+knHZfHL45mR0MZKawHZ+5XaLH4rPK1AA== -----END RSA PRIVATE KEY-----^; my $rsa_priv = Crypt::OpenSSL::RSA->new_private_key($private_key_s +tring); my $plaintext = $param1 . $param2 . $param3; my $signature = $rsa_priv->sign($plaintext); return encode_base64($signature); } sub OpenSSL_Verify { my $param1 = $_[0]; my $param2 = $_[1]; my $param3 = $_[2]; my $signature = $_[3]; # instead of having a function that reads the file to a string i j +ust declare a variabele with the content of the file just to make it +more clear.. my $public_key_string = qq^-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1Hd90G9/IAvZleTi86cq b8ZdM6vzOsv/Fxs/OpaHYexKs+t2rg+f/h7hiTakXvRhN1E+N1GZ2jXSCNKniqPK aamspIqGbbylBoDm353o6DULZi7NVm/GG5+LJwZFwzTPFuH248k0sxwTjcioj0ho 06yLWPvkUXiFQslHuno6g59hC5gCn9Lh89ULkSes/7BZTXtD1mVywEnvfdRIN8rH 6Kbt+RlrYP+CzmENmdQ4jKEj7aYBY3+qjsmL4D65De6OChb21i/iyhiPhdWez8+u lPRoinxMsbnWslgiWXifVueyplL8wDDhx5yYXUwha3FYqXTSq0qk7ZsAET+ftoQ1 OwIDAQAB -----END PUBLIC KEY-----^; my $rsa_pub = Crypt::OpenSSL::RSA->new_public_key($public_key_stri +ng); my $plaintext = $param1 . $param2 . $param3; my $verify = $rsa_pub->verify($plaintext, decode_base64($signature +)); return $verify; }

      This is just an example code which I've made as close as the original as as possible but ofc, with random-names and values of the parameters. I've worked over 45 hours in 4 days so I'm a bit tired..

      Again, thanks for clarify the new_private_key and new_public_key funtions. The documentation on cpan was pretty much useless for a noob (on this topic) like me.

        i have the same problem with OpenSSL sign.. I have the code in php and i try to do it in perl and this your code is really helpful for me!
Re: Crypt::OpenSSL:RSA Questions
by locked_user sundialsvc4 (Abbot) on Jun 20, 2014 at 00:21 UTC

    Okay, great.   First of all, go get some sleep!

    Okay, somewhere in the vicinity of “June 20, 2014” in your particular time-zone, let us continue . . .   (No fair peeking ... go back to bed.)

    The key difference between the PHP approach to things, versus (shall we say ...) the Perl approach to similar things, is that PHP programs take-for-granted a very large “global implied-context.” That is to say, the entirety of the PHP interpreter, however it may have been pre-compiled to be (in all of its glorious multiple-megabytes ...) at the time that it was installed on this particular system.   Thus, all of PHP’s mechanisms are based upon simple subroutine-calls, all of which are presumed to modify this one, always-implied, always-interpreter -level “implied context.”   Mind you, there is nothing implicitly wrong with that!   However, Perl’s design-approach is not the same.   And, one very-key reason is that “PHP can more-or-less presume that it is being used by a web-server,” whereas Perl by-design cannot.

    The Perl language is equally comfortable doing “web pages” and “seriously-funky DNA-genome twiddling.”   Therefore, the core language-interpreter is extremely small, and the system very-heavily relies upon the notion of useing things, and each of those (sometimes, very-substantial ...) packages that you might use customarily rely upon “Perl objects.” Instead of relying upon any “global context” whatsoever, as PHP by-its-design can do, they rely upon self-describing objects which incorporate all of the necessary per-instance context within themselves.

    This architecture enables many things which PHP’s by-design architecture would not readily permit, such as “validating two different strings against two different SSL-keys at the same time.”   PHP’s one-and-only available architecture is strictly a global one.   (No harm, no foul ... it is a perfectly-sensible therefore perfectly-defensible position.)   Perl, on the other hand, chooses to incorporate all of that contextual information into an object.   All of the necessary “magic” is “magically” incorporated into the system by means of use, and the perlguts of “exactly how the trick was done” are delicately concealed from view.

    The key difference between the two, then, is simply this:   whereas the PHP interpreter absorbs all of the necessary data-structures into an out-of-sight “global context,” and builds all of the available functionality directly into the php executable at compile-time, by very-legitimate design, the perl executable by-design does neither.   Any “contextual” information, instead of being hidden “somewhere in the guts of” the language-system, will be encapsulated in a programming-language object.   And, all of the functionality needed to use it, instead of being buried in the at-compile-time process, will be fully and dynamically exposed.

    Here are two entirely-different (yet, equally-valid ...) approaches to the self-same business task.   Like I said, get some sleep . . .

      I went to sleep before you posted your latest reply. I've been completely crashed today, not that surprising though.

      I really liked your post, it was a great read!

      Btw, is there a way that I can marke this as solved or is that not used on this site?