crypto/rsa doesn't seem to have OpenSSL's rsa_private_encrypt

1,927 views
Skip to first unread message

Mike Arpaia

unread,
Oct 24, 2013, 2:34:09 PM10/24/13
to golan...@googlegroups.com
Hey everyone,


The Chef API (http://docs.opscode.com/auth.html) requires HTTP requests to include a set of headers that are signed with a user's RSA private key. The Python API client (https://github.com/coderanger/pychef/blob/master/chef/rsa.py#L179) and the official Ruby API client (https://github.com/opscode/chef/blob/master/lib/chef/http/auth_credentials.rb#L50) both use OpenSSL's "rsa_private_encrypt" function.

When trying to implement this functionality in Go, there doesn't seem to be an equivalent function. Using PyChef as a comparison, trying to sign the exact same data with the exact same private key produces different signatures.



So far, I've tried using crypt/rsa's "SignPKCS1v15" and as this stackoverflow states, that incorrect for a number of reasons: http://stackoverflow.com/questions/18011708/encrypt-message-with-rsa-private-key-as-in-openssls-rsa-private-encrypt

Also, at around 6PM on May 31, 2013, there was a conversation in #go-nuts about this same topic (from a person trying to do the same thing): https://botbot.me/freenode/go-nuts/2013-06-01/

The solution that they came up with in #go-nuts was to use crypt/rsa's "EncryptPKCS1v15". I've tried that (and just about everything else in crypt/rsa) to no avail.



The code that implements the (currently broken) API client, a unit test to test the code with and this explanation are all on github if you can/want to take a look: https://gist.github.com/marpaia/7142523

Does anybody have any ideas on things that I can do to get this working properly? I fear that there's nothing in crypto/rsa that I can use. I'm totally fine implementing something if someone has any tips?

Mike

agl

unread,
Oct 24, 2013, 6:30:02 PM10/24/13
to golan...@googlegroups.com
On Thursday, October 24, 2013 2:34:09 PM UTC-4, Mike Arpaia wrote:
The Chef API (http://docs.opscode.com/auth.html) requires HTTP requests to include a set of headers that are signed with a user's RSA private key. The Python API client (https://github.com/coderanger/pychef/blob/master/chef/rsa.py#L179) and the official Ruby API client (https://github.com/opscode/chef/blob/master/lib/chef/http/auth_credentials.rb#L50) both use OpenSSL's "rsa_private_encrypt" function.

When trying to implement this functionality in Go, there doesn't seem to be an equivalent function. Using PyChef as a comparison, trying to sign the exact same data with the exact same private key produces different signatures.

I'm afraid that it's not clear to me exactly what you're trying to implement here.

Can you provide a public key, data and a valid signature of that data? I should be able to figure out what it expected from that.


Cheers

AGL

artyom.p...@gmail.com

unread,
Oct 26, 2013, 12:07:11 PM10/26/13
to golan...@googlegroups.com
Hi,

Let me join this conversation. Mike and I is trying to achieve interoperability of Go program with software relying on openssl's RSA_private_encrypt function.

Consider the following example:

kaori:tmp artyom$ date > input.txt
kaori:tmp artyom$ openssl rsautl -sign -inkey id_rsa -out openssl.out -in input.txt 
kaori:tmp artyom$ file openssl.out 
openssl.out: data
kaori:tmp artyom$ openssl rsautl -verify -inkey id_rsa -in openssl.out 
Sat Oct 26 19:41:48 MSK 2013

Despite the name, `openssl rsautl -sign` actually uses RSA_private_encrypt function to ENCRYPT input with PRIVATE key, so output can be decoded back to its original form. Some software use this kind of "signing" in their APIs, so, AFAIK, there's no standard way to talk to these APIs from Go as its stdlib does not provide any function to do the same kind of encryption.

You can find example at https://gist.github.com/artyom/7170944#file-example-md -- it's a private key, output of openssl commands for reference and a small Go program producing openssl's incompatible output. It would be great if we can create with Go the same output as `openssl rsautl -sign -inkey id_rsa -out openssl.out -in input.txt`.


--
Regards,
Artyom

Mike Arpaia

unread,
Oct 26, 2013, 3:19:30 PM10/26/13
to artyom.p...@gmail.com, golan...@googlegroups.com
Yes, exactly. Artyom is completely correct. 

After speaking with a few people on #go-nuts about the issue, the common consensus was to wrap OpenSSL's C that implements RSA_private_encrypt with Cgo but I'd obviously prefer to be able to do this in native Go (if it's possible).


--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Mike Arpaia

unread,
Oct 26, 2013, 6:12:01 PM10/26/13
to artyom.p...@gmail.com, golan...@googlegroups.com
Additionally, if anyone wants an example of what this is actually calling and how, check out this version of it in Python, using ctypes: https://gist.github.com/marpaia/7175188

al...@lx.lc

unread,
Oct 26, 2013, 7:29:19 PM10/26/13
to golan...@googlegroups.com, artyom.p...@gmail.com
This should work.  I've spent way too much time researching this, and had fun trying.  Could use error handling, better fmt, etc, but I was happy to at last have equal results.  It is a butchering of agl's 'decrypt' function.

Please let me know if it doesn't work on your machine - it won't work in playground obviously.


Thanks,
Alex

Artyom Pervukhin

unread,
Oct 27, 2013, 3:58:45 AM10/27/13
to golan...@googlegroups.com
Great job, Alex!

The code works great. I've added input size check http://play.golang.org/p/dGTl9siO8E


--
Thanks,
Artyom

Mike Arpaia

unread,
Oct 27, 2013, 12:44:35 PM10/27/13
to Artyom Pervukhin, golan...@googlegroups.com
Thanks Alex!! This is great.

Adam Langley

unread,
Oct 28, 2013, 5:02:26 PM10/28/13
to artyom.p...@gmail.com, golang-nuts
On Sat, Oct 26, 2013 at 12:07 PM, <artyom.p...@gmail.com> wrote:
> Let me join this conversation. Mike and I is trying to achieve
> interoperability of Go program with software relying on openssl's
> RSA_private_encrypt function.
>
> Consider the following example:
>
> kaori:tmp artyom$ date > input.txt
> kaori:tmp artyom$ openssl rsautl -sign -inkey id_rsa -out openssl.out -in
> input.txt
> kaori:tmp artyom$ file openssl.out
> openssl.out: data
> kaori:tmp artyom$ openssl rsautl -verify -inkey id_rsa -in openssl.out
> Sat Oct 26 19:41:48 MSK 2013

What this is doing signing the data directly, without hashing. That
means that there's a strict size limit on the message based on the
modulus of the key.

If you apply the attached patch to crypto/rsa, it'll let you sign
directly by using crypto.Hash(0) when specifying the hash function,
e.g.: sig, err := rsa.SignPKCS1v15(nil, priv, crypto.Hash(0),
signedData)

If this is useful to people (and it seems to be), it's a candidate for
inclusion after the 1.2 release.


Cheers

AGL
patch

al...@lx.lc

unread,
Oct 28, 2013, 7:25:52 PM10/28/13
to golan...@googlegroups.com
Agl, do you plan on adding a helper function, named appropriately, that does this? I myself don't need the functionality, but it seems some will, and the proposed patch will not help future users looking for an easy answer, unless it is well documented. Just my thoughts.

Thanks,
Alex

Adam Langley

unread,
Oct 29, 2013, 12:03:43 PM10/29/13
to al...@lx.lc, golang-nuts
On Mon, Oct 28, 2013 at 7:25 PM, <al...@lx.lc> wrote:
> Agl, do you plan on adding a helper function, named appropriately, that does this? I myself don't need the functionality, but it seems some will, and the proposed patch will not help future users looking for an easy answer, unless it is well documented. Just my thoughts.

I'm not sure whether it'll be a helper function or a documented mode
of SignPKCS1v15, but it won't just be dropped in there as a hidden
feature.


Cheers

AGL

agl

unread,
Jan 6, 2014, 4:14:57 PM1/6/14
to golan...@googlegroups.com, al...@lx.lc
On Tuesday, October 29, 2013 12:03:43 PM UTC-4, agl wrote:
I'm not sure whether it'll be a helper function or a documented mode
of SignPKCS1v15, but it won't just be dropped in there as a hidden
feature.

李俊杰

unread,
Aug 23, 2014, 4:17:55 AM8/23/14
to golan...@googlegroups.com
I am a newbie for golang, and I met the same problem, but I care public_decrypt more,and I can not find the Golang implement, who can help me ?many thanks!

在 2013年10月25日星期五UTC+8上午2时34分09秒,Mike Arpaia写道:

Adam Langley

unread,
Aug 23, 2014, 9:38:36 AM8/23/14
to 李俊杰, golang-nuts
On Sat, Aug 23, 2014 at 1:17 AM, 李俊杰 <phpo...@gmail.com> wrote:
> I am a newbie for golang, and I met the same problem, but I care
> public_decrypt more,and I can not find the Golang implement, who can help me
> ?many thanks!

public_decrypt is signature verification. See the Verify* functions.


Cheers

AGL

李俊杰

unread,
Aug 27, 2014, 2:48:22 AM8/27/14
to golan...@googlegroups.com, phpo...@gmail.com
I am very glad to see your reply, I implement it myself with your help yet, thank you !

在 2014年8月23日星期六UTC+8下午9时38分36秒,agl写道:
Reply all
Reply to author
Forward
0 new messages