[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Cryptographic Signatures: Ruby versus OpenSSL

Andy Stewart

8/11/2006 12:08:00 PM

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.

Any help would be much appreciated.

Thanks and regards,
Andy Stewart

6 Answers

Robert Klemme

8/11/2006 12:40:00 PM

0

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" > | 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"))

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

robert

Jano Svitok

8/11/2006 1:48:00 PM

0

On 8/11/06, Robert Klemme <shortcutter@googlemail.com> wrote:
> 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" > > | 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).
> 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.

Andy Stewart

8/11/2006 5:18:00 PM

0

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

Francis Cianfrocca

8/11/2006 5:28:00 PM

0

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
>
>

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?

Andy Stewart

8/11/2006 6:08:00 PM

0


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

> 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/

Thanks and regards,
Andy

Francis Cianfrocca

8/11/2006 7:59:00 PM

0

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?

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.