Bug #4418


Added by Ippei Obayashi about 3 years ago. Updated over 1 year ago.

Assignee:Martin Bosslet
Target version:next minor
ruby -v:ruby 1.9.2p180 (2011-02-18 revision 30909) [x86_64-linux] Backport:


OpenSSL::PKey::DH#publickey がその名前に反して DH パラメータのみを複製して返しています。
require 'openssl'
dh = OpenSSL::PKey::DH.generate(1024) # => パラメータと鍵の生成、時間がかかる
p dh.pub
key # => 公開鍵の整数を表示
p dh.publickey.pubkey # => nil

DH の場合、RSAなどのように「公開鍵とパラメータ」を取り出す需要はあまりない

fix_dh_dup.tar.gz (633 Bytes) Martin Bosslet, 02/22/2011 08:46 AM


#1 Updated by Martin Bosslet about 3 years ago


I had been doing some work in this area, so I looked into this. The problem
is that DH parameters are duplicated, but this only duplicates the generator
g and the prime p, but not the public key, which can be derived from g and p.

The easiest way to fix this is to simply dup the existing value and assign it
to the dup'ed DH instance.

Patch and test are attached.


#2 Updated by Yui NARUSE about 3 years ago

  • Status changed from Open to Assigned
  • Assignee set to Hiroshi Nakamura



#3 Updated by Ippei Obayashi about 3 years ago

Hi, Martin

Your fix is appropriate.
However, I feel no one needs this (copying only
parameters and a public key) method, so
it is also a reasonable idea that we simply remove
or rename the method.


#4 Updated by Martin Bosslet about 3 years ago

Hi Ippei,

I see your point now. There is some confusion if we look
at the EC key agreement interface. There, EC#dhcomputekey
takes what is returned by EC#publickey as a parameter,
which could be assumed the natural equivalent to what
key returns.
Maybe DH#computekey could additionally support a
version where it takes the "public
key" instead of the
"pubkey". This way we would achieve consistency among
DH and ECDH interfaces and DH#public
key wouldn't be
as useless anymore :)

What do you think?


#5 Updated by Ippei Obayashi about 3 years ago

Hi, Martin

RSA#publickey returns a RSA object, DSA#publickey returns a
DSA object, but EC#public_key does not return a EC object (it returns a EC::Point object).
I feel this fact is also confusing.

#6 Updated by Martin Bosslet about 3 years ago

Hello Ippei,

I thought this to be confusing, too - that EC#publickey is an EC::Point instead of an instance of EC itself. But when I had a closer look again, I noticed that EC::Point is in fact a subclass of EC, so the analogy to RSA and DSA is kept. So we could still have the version where DH#computekey and EC#dhcomputekey take the return value of the corresponding #public_key methods, relying on API common to EC and DH.

Best regards,

#7 Updated by Hiroshi Nakamura almost 3 years ago

  • Priority changed from Normal to Low

I agree with DH interface is confusing.

  • DH#p ... DH parameter p
  • DH#g ... DH parameter g
  • DH#public_key ... DH parameter (DHParameterSpec in Java)
  • DH#priv_key ... private value: S
  • DH#pub_key ... exchange value: gS mod p

We should have PKey::DH::Params class as same as PKey::EC::Point in the future though I don't know it's good to define it as a subclass of DH.

Back to the topic, DH#publickey is needed for exchanging DH parameters (p and g) so we cannot drop it. And we would need new method DH#params as a copy of DH#publickey when we implement DH::Params class.

#8 Updated by Martin Bosslet almost 3 years ago

Hiroshi NAKAMURA wrote:

I agree with DH interface is confusing.

Adding to the confusion is that DH implements the PKey interface in OpenSSL (OpenSSL itself, not Ruby's ext/openssl), but it conceptually is not really like the other PKey implementations.

  1. PKey offers PKey#sign and PKey#verify as a common characteristic. DH responds to both in OpenSSL, but they ultimately lead to an error saying that signature/verification is not supported.
  2. PKeys offer a public and a private "key", which at first glance is conceptually fine for DH, as there is also a public and a private part. But the analogy ends when it comes to en-/decoding their PEM/DER representation. The rest allows a "private" encoding as well as a X.509 "PUB_KEY" encoding, both of which DH does not support. As a consequence it also does not work with the new OpenSSL::PKey.read functionality.

This and the matters already discussed lead me to the conclusion that it might be a good idea to separate DH from the PKey implementations in ext/openssl and set up a separate KeyExchange module featuring two implementations, DH and ECDH (and possibly more in the future). By this separation, we could also clean up the confusion with PKey::EC, as in its current form it's some sort of hybrid, featuring both PKey and DH functionality.

The separation could also concentrate on Key Exchange/Agreement features better: We could add support for Key Derivation algorithms to simplify arbitrary-length symmetric key generation for Ciphers (a non-trivial task that needs to be taken care of manually right now), and it would be easier to design a nice API for supporting key agreement using static and ephemeral keys as outlined in NIST SP 800-56A.

What do you think about this (post 1.9.3, of course :)?

We should have PKey::DH::Params class as same as PKey::EC::Point in the future though I don't know it's good to define it as a subclass of DH.

Great idea, and we could even call it params instead of publickey if we went the "separate module approach", making it possible to rename privkey and pubkey to privatekey and public_key!


#9 Updated by Hiroshi Nakamura almost 3 years ago

  • Target version set to 2.0.0

#10 Updated by Hiroshi Nakamura over 1 year ago

  • Assignee changed from Hiroshi Nakamura to Martin Bosslet
  • Target version changed from 2.0.0 to next minor

I like to keep ext/openssl just reflects OpenSSL API but we already have some exceptions in API for ease of use.

I postponed this to "next minor" but as we talked at RubyConf, we can try it at openssl gem (vaporgem ATM.)

Also available in: Atom PDF