# Cryptographic Signatures: Ruby versus OpenSSL

**URL:** <https://rubytalk.org/t/cryptographic-signatures-ruby-versus-openssl/29862>\
**Category:** ruby-talk\
**Created:** [11 August 2006 12:07 UTC](https://rubytalk.org/t/cryptographic-signatures-ruby-versus-openssl/29862 "2006-08-11T12:07:30Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![Andy\_Stewart](https://avatars.discourse-cdn.com/v4/letter/a/8e7dd6/32.png) [@Andy\_Stewart](https://rubytalk.org/u/Andy_Stewart)\
**Post date:** [11 August 2006 12:07 UTC](https://rubytalk.org/t/cryptographic-signatures-ruby-versus-openssl/29862/1 "2006-08-11T12:07:30Z")

</div>

Hello Everyone,

I am having problems matching up a signature created with openssl on the command line with a signature created in Ruby.

The signature I am trying to get is an RSA encryption with my 1024 bit private key of a SHA-1 hash of data.

This is what I did on the command line:

$ openssl genrsa -out private.pem 1024  
$ echo -n "Some text to sign" \  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\> openssl dgst -sha1 -binary \  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\> openssl rsautl -sign -inkey private.pem \  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\> openssl enc -base64

This is what I did in Ruby:

require 'base64'  
require 'openssl'  
include OpenSSL  
include PKey  
include Digest

private\_key = RSA.new(File.open("/Users/andy/tmp/private.pem").read)  
signature = private\_key.sign(OpenSSL::Digest::SHA1.new, "Some text to sign")  
puts Base64.encode64(signature)

Unfortunately the base64-encoded signatures produced by each method don't match.

I have spent quite a lot of time with Google and the RubyPKI source -- but I am new to Ruby and have exhausted all the avenues I can think of.

Any help would be much appreciated.

Thanks and regards,  
Andy Stewart

---

<div class="post-metadata">

**Author:** ![Robert\_K1](https://yyz1.discourse-cdn.com/flex029/user_avatar/rubytalk.org/robert_k1/32/1830_2.png) [@Robert\_K1](https://rubytalk.org/u/Robert_K1)\
**Post date:** [11 August 2006 12:40 UTC](https://rubytalk.org/t/cryptographic-signatures-ruby-versus-openssl/29862/2 "2006-08-11T12:40:05Z")

</div>

Could it be that in your Ruby script you're missing out the equivalent step of "| openssl dgst -sha1 -binary \"? I'd rather have expected something like

signature = private\_key.sign(OpenSSL::Digest::SHA1.new("Some text to sign"))

For testing purposes I'd use the same \*file\* (i.e. in the file system). And you should open that in binary mode from within Ruby to be sure both tools see the same.

I'd probably work through this step by step, i.e. compare the output of every step from the first step on. That way you can easily detect where it goes wrong. HTH

Kind regards

&nbsp;&nbsp;robert

> **···**
>
> On 11.08.2006 14:07, Andy Stewart wrote:
> 
> > Hello Everyone,
> > 
> > I am having problems matching up a signature created with openssl on the command line with a signature created in Ruby.
> > 
> > The signature I am trying to get is an RSA encryption with my 1024 bit private key of a SHA-1 hash of data.
> > 
> > This is what I did on the command line:
> > 
> > $ openssl genrsa -out private.pem 1024  
> > $ echo -n "Some text to sign" \  
> > &nbsp;&nbsp;&nbsp;&nbsp;\> openssl dgst -sha1 -binary \  
> > &nbsp;&nbsp;&nbsp;&nbsp;\> openssl rsautl -sign -inkey private.pem \  
> > &nbsp;&nbsp;&nbsp;&nbsp;\> openssl enc -base64
> > 
> > This is what I did in Ruby:
> > 
> > require 'base64'  
> > require 'openssl'  
> > include OpenSSL  
> > include PKey  
> > include Digest
> > 
> > private\_key = RSA.new(File.open("/Users/andy/tmp/private.pem").read)  
> > signature = private\_key.sign(OpenSSL::Digest::SHA1.new, "Some text to sign")  
> > puts Base64.encode64(signature)
> > 
> > Unfortunately the base64-encoded signatures produced by each method don't match.
> > 
> > I have spent quite a lot of time with Google and the RubyPKI source -- but I am new to Ruby and have exhausted all the avenues I can think of.

---

<div class="post-metadata">

**Author:** ![Francis\_Cianfrocca](https://avatars.discourse-cdn.com/v4/letter/f/7bcc69/32.png) [@Francis\_Cianfrocca](https://rubytalk.org/u/Francis_Cianfrocca)\
**Post date:** [11 August 2006 13:45 UTC](https://rubytalk.org/t/cryptographic-signatures-ruby-versus-openssl/29862/3 "2006-08-11T13:45:11Z")

</div>

I got it. Use RSA::private\_encrypt rather than RSA::sign to replicate what  
you are doing on the command line.

---

<div class="post-metadata">

**Author:** ![Francis\_Cianfrocca](https://avatars.discourse-cdn.com/v4/letter/f/7bcc69/32.png) [@Francis\_Cianfrocca](https://rubytalk.org/u/Francis_Cianfrocca)\
**Post date:** [11 August 2006 13:50 UTC](https://rubytalk.org/t/cryptographic-signatures-ruby-versus-openssl/29862/4 "2006-08-11T13:50:23Z")

</div>

This Ruby code will give you the same result:

> **···**
>
> #--------------------------------------------------  
> require 'base64'  
> require 'openssl'  
> require 'sha1'  
> include OpenSSL  
> include PKey  
> include Digest
> 
> pkey = RSA.new(File.read("private.pem"))  
> plaintext = SHA1.new( "Some Text" ).digest  
> enc = pkey.private\_encrypt(plaintext)  
> puts Base64.encode64(enc)
> 
> #--------------------------------------------------------
> 
> as this:
> 
> echo -n "Some Text" | openssl dgst -sha1 -binary | openssl rsautl -sign  
> -inkey private.pem | openssl enc -base64

---

<div class="post-metadata">

**Author:** ![Francis\_Cianfrocca](https://avatars.discourse-cdn.com/v4/letter/f/7bcc69/32.png) [@Francis\_Cianfrocca](https://rubytalk.org/u/Francis_Cianfrocca)\
**Post date:** [11 August 2006 13:32 UTC](https://rubytalk.org/t/cryptographic-signatures-ruby-versus-openssl/29862/5 "2006-08-11T13:32:16Z")

</div>

On 8/11/06, Robert Klemme \<shortcutter@googlemail.com\> wrote: Could it be  
that in your Ruby script you're missing out the equivalent

> step of "| openssl dgst -sha1 -binary \"? I'd rather have expected  
> something like

I think he's doing the Ruby part right. The OpenSSL code underneath the  
Ruby library-calls automatically does the hashing for you, which is why  
you have to give it a hash algorithm when generating an RSA sig. I think  
something is wrong with how he's using rsautl.

---

<div class="post-metadata">

**Author:** ![Jan\_Svitok](https://avatars.discourse-cdn.com/v4/letter/j/cab0a1/32.png) [@Jan\_Svitok](https://rubytalk.org/u/Jan_Svitok)\
**Post date:** [11 August 2006 13:48 UTC](https://rubytalk.org/t/cryptographic-signatures-ruby-versus-openssl/29862/6 "2006-08-11T13:48:24Z")

</div>

> \> Hello Everyone,  
> \>  
> \> I am having problems matching up a signature created with openssl on the  
> \> command line with a signature created in Ruby.  
> \>  
> \> The signature I am trying to get is an RSA encryption with my 1024 bit  
> \> private key of a SHA-1 hash of data.  
> \>  
> \> This is what I did on the command line:  
> \>  
> \> $ openssl genrsa -out private.pem 1024  
> \> $ echo -n "Some text to sign" \  
> \> \> openssl dgst -sha1 -binary \  
> \> \> openssl rsautl -sign -inkey private.pem \  
> \> \> openssl enc -base64  
> \>  
> \> This is what I did in Ruby:  
> \>  
> \> require 'base64'  
> \> require 'openssl'  
> \> include OpenSSL  
> \> include PKey  
> \> include Digest  
> \>  
> \> private\_key = RSA.new(File.open("/Users/andy/tmp/private.pem").read)  
> \> signature = private\_key.sign(OpenSSL::Digest::SHA1.new, "Some text to  
> \> sign")  
> \> puts Base64.encode64(signature)  
> \>  
> \> Unfortunately the base64-encoded signatures produced by each method  
> \> don't match.  
> \>  
> \> I have spent quite a lot of time with Google and the RubyPKI source --  
> \> but I am new to Ruby and have exhausted all the avenues I can think of.
> 
> Could it be that in your Ruby script you're missing out the equivalent  
> step of "| openssl dgst -sha1 -binary \"? I'd rather have expected  
> something like
> 
> signature = private\_key.sign(OpenSSL::Digest::SHA1.new("Some text to  
> sign"))

It seems it's not neccessary, sign will do that.

> For testing purposes I'd use the same \*file\* (i.e. in the file system).  
> &nbsp;&nbsp;And you should open that in binary mode from within Ruby to be sure  
> both tools see the same.
> 
> I'd probably work through this step by step, i.e. compare the output of  
> every step from the first step on. That way you can easily detect where  
> it goes wrong. HTH

From what I've seen they both should produce PKCS#1-padded signature,  
so in this case, only possible difference is that one produces block  
type 00, and the other 01, but that's not very probable (=they should  
use deterministic type of padding)

I'd try:  
- the official test vectors, to see which one is right  
- using cmdline tools and/or Bignumber \*\* and % to decrypt the  
signature to see the padding  
- crossverification of the respective signatures (i.e. whether cmdline  
verifies ruby-generated signature and vice versa)  
- stepping through RSA#sign, as it is written in ruby.

Disclaimer: I don't know what version do you have, nor what version  
I've looked at, so I may be wrong.

> **···**
>
> On 8/11/06, Robert Klemme \<shortcutter@googlemail.com\> wrote:
> 
> > On 11.08.2006 14:07, Andy Stewart wrote:

---

<div class="post-metadata">

**Author:** ![Andy\_Stewart](https://avatars.discourse-cdn.com/v4/letter/a/8e7dd6/32.png) [@Andy\_Stewart](https://rubytalk.org/u/Andy_Stewart)\
**Post date:** [11 August 2006 17:17 UTC](https://rubytalk.org/t/cryptographic-signatures-ruby-versus-openssl/29862/7 "2006-08-11T17:17:51Z")

</div>

Francis,

\> This Ruby code will give you the same result:  
\> #--------------------------------------------------  
\> [snip]  
\> #--------------------------------------------------------  
\>  
\> as this:  
\>  
\> echo -n "Some Text" | openssl dgst -sha1 -binary | openssl rsautl -sign  
\> -inkey private.pem | openssl enc -base64

That's perfect, thank you.

I'll now go and dig through RSA::private\_encrypt and RSA::sign and see how they differ.

Thank you also to Jan and Robert for your helpful comments.

Kind regards,  
Andy

---

<div class="post-metadata">

**Author:** ![Francis\_Cianfrocca](https://avatars.discourse-cdn.com/v4/letter/f/7bcc69/32.png) [@Francis\_Cianfrocca](https://rubytalk.org/u/Francis_Cianfrocca)\
**Post date:** [11 August 2006 17:28 UTC](https://rubytalk.org/t/cryptographic-signatures-ruby-versus-openssl/29862/8 "2006-08-11T17:28:20Z")

</div>

RSA#sign is basically a wrapper over EVP\_SignInit, EVP\_SignUpdate and  
EVP\_SignFinalize, which are themselves a high-level wrapper over the  
actual crypto operations. The EVP\_xxx calls do the hashing for you, so  
since you're using RSA, you have to specify a digest algorithm.

rsautl -sign is a very dumb piece of code that only encrypts your  
plaintext with a private key. You notice in your shell pipeline, you  
did the sha digest yourself. That's what I did in the Ruby code I sent  
you.

I assume you tested the Ruby output with rsautl -verify and it worked?

> **···**
>
> On 8/11/06, Andy Stewart \<ruth\_andy@fastmail.fm\> wrote:
> 
> > That's perfect, thank you.
> > 
> > I'll now go and dig through RSA::private\_encrypt and RSA::sign and  
> > see how they differ.
> > 
> > Thank you also to Jan and Robert for your helpful comments.
> > 
> > Kind regards,  
> > Andy

---

<div class="post-metadata">

**Author:** ![Andy\_Stewart](https://avatars.discourse-cdn.com/v4/letter/a/8e7dd6/32.png) [@Andy\_Stewart](https://rubytalk.org/u/Andy_Stewart)\
**Post date:** [11 August 2006 18:07 UTC](https://rubytalk.org/t/cryptographic-signatures-ruby-versus-openssl/29862/9 "2006-08-11T18:07:59Z")

</div>

> RSA#sign is basically a wrapper over EVP\_SignInit, EVP\_SignUpdate and  
> EVP\_SignFinalize, which are themselves a high-level wrapper over the  
> actual crypto operations. The EVP\_xxx calls do the hashing for you, so  
> since you're using RSA, you have to specify a digest algorithm.

So what's the difference between:

- a signature specifying RSA on top of SHA-1  
- RSA encryption using a private key of SHA-1 hashed data?

Conceptually they are the same, I believe, so why do RSA::private\_encrypt and RSA::sign behave differently?

> I assume you tested the Ruby output with rsautl -verify and it worked?

Yes indeed. I did:

$ ruby sig.rb | openssl enc -base64 -d | openssl rsautl -verify -inkey public.pem -pubin | xxd

And that wrote out the SHA-1 digest of my original data.

By the way, the pipeline came from Allan Odgaard here: [http://macromates.com/sigpipe/archives/2004/09/05/using-openssl-for-license-keys/](http://macromates.com/sigpipe/archives/2004/09/05/using-openssl-for-license-keys/)

Thanks and regards,  
Andy

> **···**
>
> On 11 Aug 2006, at 18:28, Francis Cianfrocca wrote:

---

<div class="post-metadata">

**Author:** ![Francis\_Cianfrocca](https://avatars.discourse-cdn.com/v4/letter/f/7bcc69/32.png) [@Francis\_Cianfrocca](https://rubytalk.org/u/Francis_Cianfrocca)\
**Post date:** [11 August 2006 19:59 UTC](https://rubytalk.org/t/cryptographic-signatures-ruby-versus-openssl/29862/10 "2006-08-11T19:59:29Z")

</div>

The protocol for digital signatures (oversimplifying) is to encrypt  
(sign) with a private key and decrypt (verify) with a public key.  
That's what RSA::private\_encrypt is for. (If you're using encryption  
in order to hide data instead of verify it, you encrypt with a public  
key.)

But asymmetric encryption is exceptionally costly, so signatures are  
always done by encrypting a "digest" (a cryptographically-strong hash)  
of the plaintext rather than the whole text- that's where SHA-1 comes  
in. Now you only have to encrypt 20 bytes with your private key.

RSA::sign does the hashing as well as the encrypting for you. It's a  
convenience function. Several layers below, a private-key encryption  
gets done just as with RSA::private\_encrypt.

> **···**
>
> On 8/11/06, Andy Stewart \<ruth\_andy@fastmail.fm\> wrote:
> 
> > So what's the difference between:
> > 
> > - a signature specifying RSA on top of SHA-1  
> > - RSA encryption using a private key of SHA-1 hashed data?
> > 
> > Conceptually they are the same, I believe, so why do  
> > RSA::private\_encrypt and RSA::sign behave differently?
