[botan-devel] PEM_encode and ECDH_PrivateKey

Jack Lloyd lloyd at randombit.net
Wed Feb 1 18:11:21 EST 2012

On Wed, Feb 01, 2012 at 02:11:52PM -0800, Sean Cassidy wrote:
> Hello,
> I don't think the OID for ECDH is properly configured.
> OIDS::lookup("ECDH"), the algorithm name given in ecdh.h, results in
> an exception. Here is some code that exhibits this problem in v1.10.1
> on Ubuntu:

This is kind of a bug but also somewhat intentional. The issue is that
ANSI X9.62 in its infinite wisdom decided that the same format *and
the same OID* would be used to identify both ECDSA and ECDH keys. So
serializing an ECDH key is easy, just set the OID. The problem comes
when loading a key. There is no way to distinguish if it should be an
ECDSA or ECDH key. Lacking any good approach I punted and defined the
OID for ECDSA only on the theory that ECDH is rare.

There are a few solutions possible, none particularly appealing

 - Define a new OID for ECDH. The optimal solution if you only care
   about interoperating with botan, not so great if you need to
   interact with a system that can't be configured with new OIDs.
   Actually checking further it seems that this has already been
   done: is defined specifically for ECDH. However
   a quick check shows virtually nobody uses/supports it :(

 - Use the X9.62 OID for ECDH as well, with the understanding that
   when you deserialize (eg PKCS8::load_key) a ECDH key you'll get
   back an ECDSA key object and you'll have to transfer the values
   into an ECDH key object before using it. This assumes you have some
   additional contextual information at load time to know when this
   is/isn't necessary.

 - Flatten the ECC key hierarchy in the code, effectively merging
   ECDSA and ECDH classes. This does solve the issue; I find it rather
   distasteful but so it goes when you deal with standards. However
   this couldn't happen in 1.10 as it would break ABI, so no quick fix
   this way in any case.

Either of the first two cases you can do in your application code
right now. For instance to use the ECDSA OID, add this to your main
right after LibraryInitializer runs:

   Library_State& botan_state = global_state();
   const std::string ecdh_oid = "1.2.840.10045.2.1";

   if(!botan_state.is_set("oid2str", ecdh_oid))
      botan_state.set("oid2str", ecdh_oid, "ECDH");

   if(!botan_state.is_set("str2oid", "ECDH"))
      botan_state.set("str2oid", "ECDH", ecdh_oid);

The same approach could be used for the OID.

I think it's a gimme to support reading ECDH with the OID
out of the box. Then people who want to signal specifically ECDH can
easily do so. (Ideally with an easier to understand API than the one
I'm using above to set the ECDH OID). Beyond that, I'm still unsure
what exactly the best long term solution may be.

You're apparently the first person who has come up against this (or at
least the first to mention it), so any comments about what you're
trying to do in the larger sense, what systems you want to interop
with, etc would act as increasing my ECDH user sample set from 0 to 1,
a substantial improvement.


More information about the botan-devel mailing list