Ruby openssl ECC help plz

I am confused on how to properly export public ECC key. I can see it
only if I export both public key and private key with to_text, which is
bad. Otherwise how do I export just the public key? I have two ideas :

require “openssl”

puts OpenSSL::PKey::EC.builtin_curves
cipher = OpenSSL::Cipher::Cipher.new(“AES-256-OFB”)

key = OpenSSL::PKey::EC.new(“prime192v1”)
key.generate_key
puts key.to_pem(cipher, “testing”)

#my first guess, and what I still think seems most likely to be correct
a = key.public_key
puts a.to_bn

#however this produces a 936 bit number and I think my public key should
be #much smaller than this…is converting it to a big number changing
the #bit size and confusing me ?

#Pretty sure this is wrong…

puts key.dh_compute_key(a).bytesize

#Because I think this generates a ECDH shared secret using the public
key #of someone else (if they ever manage to export it…). But I have
my own #questions about this. Why does it take only one parameter? Ok
the #elliptic curve is already specified with key, and then their public
key, #but how do I specify my private key? Also this makes a shared
secret (I #think that is what it is doing) that is under 256 bits but
with my #elliptic curve set at what it is I would think the shared
secret would be #slightly over 256 bits…

also any help to clarify ruby openssl ecc is appreciated the
documentation is extremely lacking and I start to get it figured out but
it is much harder than the using ruby RSA or any of the symmetric
algorithms, and also much less documented (these things are related)

thanks!

Am 31. Mrz 2012 02:16 schrieb no name removed_email_address@domain.invalid:

I am confused on how to properly export public ECC key. I can see it
only if I export both public key and private key with to_text, which is
bad. Otherwise how do I export just the public key?

It’s a bit tricky in the sense that you need to create a second EC
instance
which will only be assigned the public key. Unfortunately you can’t to
the
straightforward thing ec.public_key.to_der, but you can do it like this:

key = OpenSSL::PKey::EC.new
key.group = OpenSSL::PKey::EC::Group.new(‘prime256v1’)
key.generate_key

pub = OpenSSL::PKey::EC.new(key.group)
pub.public_key = key.public_key
pem = pub.to_pem # to_der is possible, too, of course

gives you the public key encoding:

-----BEGIN PUBLIC KEY-----
MFkw…
-----END PUBLIC KEY-----

key #of someone else (if they ever manage to export it…). But I have
my own #questions about this. Why does it take only one parameter? Ok
the #elliptic curve is already specified with key, and then their public
key, #but how do I specify my private key?

You don’t have to - you are calling #dh_compute_key on an instance of
EC,
which consists of both the public key (point) and the private key
(integer),
and the parameter you pass in is the peer’s public key (point).

Also this makes a shared
secret (I #think that is what it is doing) that is under 256 bits but
with my #elliptic curve set at what it is I would think the shared
secret would be #slightly over 256 bits…

Hmm, the result should always be of the same size, it depends on the
actual curve what its output size finally will be. Which curve are you
using?

also any help to clarify ruby openssl ecc is appreciated the
documentation is extremely lacking and I start to get it figured out but
it is much harder than the using ruby RSA or any of the symmetric
algorithms, and also much less documented (these things are related)

Yes, I am aware of that, when I have the time, we’ll add more docs!

Thanks I have it working now. I have one other question, why doesn’t
ruby openssl support counter mode of operation??

Am 31. Mrz 2012 12:04 schrieb no name removed_email_address@domain.invalid:

Thanks I have it working now. I have one other question, why doesn’t
ruby openssl support counter mode of operation??

Ruby’s Cipher class supports whatever OpenSSL’s EVP_CIPHER interface
supports. Unfortunately, CTR mode never made it there until just
recently.
Now finally, 1.0.1 supports AES in CTR mode. If you are interested in
using
it, you may want to upgrade to 1.0.1 and then you can also use it from
Ruby
like this:

cipher = OpenSSL::Cipher.new(‘aes-128-ctr’)

Regards,
Martin

thanks for the help. I am having a hellish time getting ruby to
recognize the updated openSSL. First I compile new one from source,
since it is not in the repository of my OS. After I compile the new
version OpenSSL still thinks it is (and therefor is…) the old version
that came with my OS. So I need to completely remove OpenSSL and then
install from source. Great now OpenSSL is the newest version! But
crap…

OpenSSL::Cipher::Cipher.new(“AES-128-CTR”)

it says not a supported cipher (and I tried 256 and lower case also just
in case I made simple mistake here, but OFB and such still work so it is
actually not recognizing the mode)

when I do

puts OpenSSL::VERSION

it says I run 1.0.1 which is good, seems things should work ?!

but when I run

OpenSSL::OPENSSL_VERSION

it says OpenSSL 1.0.0e

so I think the problem may be this since it says 1.0.0e instead of 1.0.1
(of course I have no idea the difference between running VERSION and
OPENSSL_VERSION , the documentation does not answer this well enough for
me to exactly understand the distinction)

I have reinstalled ruby from source a dozen times now trying different
things. I try to point it at the directory I install 1.0.1 to with
–with-openssl-dir=/path/to/openssl as I see many suggest and it has no
idea what I am talking about (invalid option in new version of Ruby it
seems).

I try for hours now to get ruby to work with the new version of openssl
so I can use CTR mode but nothing I do works and I really can’t think of
what else I could possibly try at this point, and no amount of google is
helping I have exhausted the pages.

Again thanks for your help … I tried to figure getting this to work
out myself but have failed and am at a total dead end at this point

actually I don’t even see how it can possibly be using the old version
since I entirely purge it and the only version of OpenSSL is 1.0.1 yet
still ruby says CTR is not supported (and says 1.0.0e for
OPENSSL_VERSION, but not VERSION)

it seems as likely to be a problem with Ruby to me as a problem with
OpenSSL at this point, although in either case it is probably a user
error on my part. Have you actually gotten ruby to work with ctr mode?

Yes, I got it working here. I’m very confident you’re having the problem
I
described in my previous response, applying the steps there should solve
the problem.

yes I didn’t read your post before I made my second post (which I tried
to delete).

it gets stuck with this error I try to recompile everything with fPIC
flag but it still happens

/usr/bin/ld: /usr/local/ssl/lib/libcrypto.a(e_gost_err.o): relocation
R_X86_64_32 against `.data’ can not be used when making a shared object;
recompile with -fPIC
/usr/local/ssl/lib/libcrypto.a: could not read symbols: Bad value
collect2: ld returned 1 exit status

I think I am probably just going to stick with OFB, and avoid the
headaches of trying to update OpenSSL and get it to work with Ruby.
Maybe some day my distro will have 1.0.1 in the repository :<

make clean is my friend

thanks! all is good now.

Am 1. April 2012 02:57 schrieb randompasswords arenotgoodidea
removed_email_address@domain.invalid:

it says not a supported cipher (and I tried 256 and lower case also just

things. I try to point it at the directory I install 1.0.1 to with
but omfg why so hard to do such a simple thing 0_0

The problem is that when you recompile Ruby with --with-openssl-dir,
this won’t get passed through to the step when the actual OpenSSL
extension will be built. You could upgrade your OpenSSL on the OS
level, but you probably don’t want to if it’s not in the package system
yet. Then things would work automagically, but you can still get
1.0.1 support with a custom OpenSSL installation:

Ruby OpenSSL is a C extension that has its own build process
using an extconf.rb file. So what you can do is go to your Ruby
source directory, and there to ext/openssl.
Run
ruby extconf.rb --with-openssl-dir=/path/to/openssl1.0.1
then
make
This will produce openssl.so. Take that file and go to the directory
where your Ruby installation lives, there you go to
lib/ruby/1.9./i686 (32bit)
or
lib/ruby/1.9.x/x86_64… (64 bit, depends on your OS, you’ll only find
native libraries in it)

and replace the file openssl.so (or .dynlib or .dll) with the one you
just
compiled.

Now ruby -ropenssl -e 'puts OpenSSL::OPENSSL_VERSION should
print the desired 1.0.1.

-Martin

I have a question about ECDH and I will put it here since there is no
need to make two threads.

dh_compute_key(pub.public_key)

returns a string. I need the integer value. .to_i doesn’t work. How can
I get the integer value?

Am 11. April 2012 15:13 schrieb ruby ismyname removed_email_address@domain.invalid:

I have a question about ECDH and I will put it here since there is no
need to make two threads.

dh_compute_key(pub.public_key)

returns a string. I need the integer value. .to_i doesn’t work. How can
I get the integer value?

Just to make sure - the computed secret is the x coordinate of some
point,
and what you would like to have is an integer representation of that?

-Martin

Yes, what I am implementing requires me to treat the shared secret and
the public key as integers. .to_bn works for the public key but I am
stuck on the shared secret. I think I might be kind of close to figuring
it out:

q = OpenSSL::PKey::EC.new(“secp128r2”)
q.generate_key

pub = OpenSSL::PKey::EC.new(q.group)
pub.public_key = q.public_key

a = pub.public_key.to_bn

ss = q.dh_compute_key(pub.public_key)

puts ss.unpack(‘I>*’)

this puts a series of numbers such as the following:

2755907301
4161034086
221727499
1603331514

or

2041301904
2634281936
2269031273
1943826378

Just to see if this works, I have then been combining these into big
integers, so far just by hand. My theory is that if the resulting
integer is the same bit size as the curve, that it is an indication I
may not be doing it incorrectly. And I am so close to almost not
certainly doing it wrong, because sometimes it does make output that
equals 128 bits when I convert it to binary, for example

275590730141610340862217274991603331514

but alas sometimes it is slightly more or less than 128 bits, as with

2041301904263428193622690312731943826378

which is 131 bits

regardless of the curve I use the output is either the correct size or
near it, but I don’t understand the variation.

ss.length always returns a number of bytes that when multiplied by 8 is
the size of the curve, assuming that the curve consists of a number of
bits that is divisible by 8 anyway.

I could be way off on this and doing it totally wrong, but since I hit a
total dead end I figured that I might as well try doing things until I
at least get the correct size integer and then try to confirm it as
being correct further from there, but I can just get close to the right
size.

I have read this about openssl

“OpenSSL does not do it this way: it coverts the shared secret integer
into a byte string of a length equivalent to the number of significant
bytes in the shared integer.”

so pretty much what I am trying to do is just reverse this process, so
that I can convert the byte string into the shared integer. I also found
a reference that mentioned OpenSSL uses big endian, and I just assume
that the I option is correct for unpack because it is an integer being
stored. Not sure if combining the returned strings into one big string
like I am doing is the correct way of going about it, but it does get me
a string that is the correct size some times.

Wow, I talked a lot , anyway thanks for your help :).