Subject: [Curdle] Key examples in draft-ietf-curdle-pkix-03

From: str4d <[email-masked]>
Date: Wed, 14 Dec 2016 10:54:34 +0000 (UTC)

Hello,

I am currently updating my EdDSA Java library to implement the current
spec for key encoding [0] (previously I used
draft-josefsson-pkix-eddsa-04 for public keys, and the equivalent in
PKCS#8 format for private keys). The example public key given in
draft-ietf-curdle-pkix-03 [1] passes my tests, however the example
private key [2] does not.

It appears that the private key material within the example is 34 bytes,
but according to Section 3.2 of draft-irtf-cfrg-eddsa-08 [3] (which
AFAICT the present draft defers to for encoding), the private key is the
b-bit seed k, which is 32 bytes.

Am I missing something? If the example keys in the present draft are
correct, it would be helpful to add a reference that clarifies their
exact encoding.

Thanks,
Jack Grigg

[0] https://github.com/str4d/ed25519-java/pull/22
[1] https://tools.ietf.org/html/draft-ietf-curdle-pkix-03#section-10.1
[2] https://tools.ietf.org/html/draft-ietf-curdle-pkix-03#section-10.3
[3] https://tools.ietf.org/html/draft-irtf-cfrg-eddsa-08#section-3.2

---

From: Ilari Liusvaara <[email-masked]>
Date: Wed, 14 Dec 2016 14:15:15 +0200

> correct, it would be helpful to add a reference that clarifies their

Apparently the key is wrapped in OCTET STRING twice for some reason,
so the length is actually 32 bytes (the first 2 are second OCTET STRING
header).

-Ilari

---

From: David Benjamin <[email-masked]>
Date: Wed, 14 Dec 2016 13:23:05 +0000

> so the length is actually 32 bytes (the first 2 are second OCTET STRING

Is it too late to change that / was there any particular reason for this?
Not that saving or using two bytes really matters, but it seems unnecessary
when we already have an OCTET-STRING-shaped hole to put our octet string in.

David

---

From: David Benjamin <[email-masked]>
Date: Thu, 15 Dec 2016 13:26:44 +0000

On Thu, Dec 15, 2016 at 1:42 AM str4d <[email-masked]> wrote:

> On 12/15/2016 02:23 AM, David Benjamin wrote:
> Additionally, it is somewhat strange that the same document
> (draft-irtf-cfrg-eddsa-08) would define that the public key requires no
> additional OCTET STRING wrapping, while the private key does. I
> personally don't have a problem implementing it this way if that is what
> the WG decides, but one of the two documents needs to be updated
> regardless of whether or not this is changed (either to change it or to
> clarify the encoding).
>

Even if it stays as-is, I do not think draft-irtf-cfrg-eddsa should be
changed to mention the OCTET STRING wrapping. EdDSA public and private keys
are encoded as specified by draft-irtf-cfrg-eddsa-08. If you just need to
store one of those, you use it. Neither use ASN.1 at that layer since
there's no need. Serialization asks for a byte string, and we already have
a way to return a byte string.

If you need to store them in an SPKI or PKCS#8 blob, you then follow
draft-ietf-curdle-pkix which calls into that serialization and adds a bunch
of ASN.1. The PKCS#8 wrapping, for some reason, prescribes two layers of
OCTET STRING wrapping right now. This, though odd, is still self-consistent.

David

---

From: Russ Housley <[email-masked]>
Date: Thu, 15 Dec 2016 10:53:42 -0500

> Even if it stays as-is, I do not think draft-irtf-cfrg-eddsa should be changed to mention the OCTET STRING wrapping. EdDSA public and private keys are encoded as specified by draft-irtf-cfrg-eddsa-08. If you just need to store one of those, you use it. Neither use ASN.1 at that layer since there's no need. Serialization asks for a byte string, and we already have a way to return a byte string.

I do not see any OCTET STRING wrapping in the test vectors in section 7 of draft-irtf-cfrg-eddsa-08.

Russ

---

From: Russ Housley <[email-masked]>
Date: Thu, 15 Dec 2016 10:53:42 -0500

Russ

---

From: Jim Schaad <[email-masked]>
Date: Thu, 15 Dec 2016 21:52:54 -0800

I believe that the OpenSSL people would be sad if we changed this at this time.  I did some interop testing with their developers before the last version was released and the OCTET STRING wrapper on the private key is what we were doing at the time.

Jim

From: Curdle [mailto:[email-masked]] On Behalf Of David Benjamin
Sent: Wednesday, December 14, 2016 5:23 AM
To: Ilari Liusvaara <[email-masked]>; str4d <[email-masked]>
Cc: [email-masked]
Subject: Re: [Curdle] Key examples in draft-ietf-curdle-pkix-03

On Wed, Dec 14, 2016 at 7:15 AM Ilari Liusvaara <mailto:[email-masked]> wrote:

Is it too late to change that / was there any particular reason for this? Not that saving or using two bytes really matters, but it seems unnecessary when we already have an OCTET-STRING-shaped hole to put our octet string in.

David

---

From: David Benjamin <[email-masked]>
Date: Fri, 16 Dec 2016 06:56:27 +0000

Ah, yes, I see OpenSSL has already shipped code which serializes X25519 in
this way, as early as OpenSSL 1.1.0 in September. That's unfortunate. It
would have been preferable to avoid this confusing double wrapper, but so
it goes I guess.

David

On Fri, Dec 16, 2016 at 12:53 AM Jim Schaad <[email-masked]> wrote:

> I believe that the OpenSSL people would be sad if we changed this at this
> time.  I did some interop testing with their developers before the last
> version was released and the OCTET STRING wrapper on the private key is
> what we were doing at the time.
>
> Jim
>
> _______________________________________________
> Curdle mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/curdle
>

---

From: David Benjamin <[email-masked]>
Date: Fri, 16 Dec 2016 07:18:11 +0000

So we don't end up with two variants of this floating around (this thread
gives one data point of the current text being misinterpreted), What do you
think about these editorial changes?

1. In the paragraph beginning "For the keys defined in this document
[...]", add a sentence like "Note the opaque byte sequence is wrapped in
OCTET STRINGs twice in total."

2. EdPrivateKey sounds like this only applies to Ed* rather than both Ed*
and X*. It should probably be renamed. But the best name I can come up with
right now is PrivateKeyWrapper, which is terrible. Another option is to
avoid defining a type and just say:

   For the keys defined in this document, the private key is always an
   opaque byte sequence.  This is encoded in a OneAsymmetricKey
   object by wrapping the sequence in an ASN.1 OCTET STRING
   and placing its DER encoding in the 'privateKey' field. Note that
   'privateKey' is itself an OCTET STRING, so the original byte
   sequence is wrapped in OCTET STRINGs twice in total.

David

On Fri, Dec 16, 2016 at 1:56 AM David Benjamin <[email-masked]>
wrote:

David

Jim

On Wed, Dec 14, 2016 at 7:15 AM Ilari Liusvaara <mailto:
[email-masked]> wrote:

David

---

From: "Salz, Rich" <[email-masked]>
Date: Fri, 16 Dec 2016 13:06:01 +0000

> time.  I did some interop testing with their developers before the last version
> was released and the OCTET STRING wrapper on the private key is what we
> were doing at the time.

Speaking as an individual, yes.  Please don’t change this.

---

From: Benjamin Kaduk <[email-masked]>
Date: Fri, 16 Dec 2016 20:43:55 -0600

>    sequence is wrapped in OCTET STRINGs twice in total.

And/or have an appendix with an example of the full encoding for a given
dummy key?

-Ben

---

From: Benjamin Kaduk <[email-masked]>
Date: Fri, 16 Dec 2016 21:26:58 -0600

> Speaking as an individual, yes.  Please don’t change this.

It's a fairly frustrating feeling for a protocol designer to be hedged
in to a particular behavior because an implementation of a draft version
escaped into the wild and the change is not worth the pain of breaking
interoperability.  This happens all over the place, not just here, of course,
which leads to the question of what can we do to avoid getting locked into
the draft interfaces.  It's easy to point fingers and say that the
software authors should know to have a transition strategy if they ship
a protocol that is explicitly a work in progress, but that doesn't really
seem very productive.  The TLS 1.3 story seems fairly reasonable, with
a scheme to indicate support for a specific draft version as opposed to
having to squat on the version number for the final protcol, but that
seems to have evolved semi-organically as I understand it, with informal
contact among the early implementors.  Should all drafts burn a set of
codepoints and map them to the given draft versions?  Probably not.
Should they think about it?  Maybe.  Are there other techniques that
we can use to help software authors avoid shooting the ecosystem in the foot?

-Ben

---

From: str4d <[email-masked]>
Date: Fri, 16 Dec 2016 21:28:34 +0000 (UTC)

> OCTET STRING wrapping right now. This, though odd, is still self-consistent.

I've figured out the source of my confusion (and you're right, it wasn't
related to draft-irtf-cfrg-eddsa, that was my mis-remembering): section
7 of draft-ietf-curdle-pkix is somewhat obtuse (to someone not
well-versed in IETF lingo) as to how the various ASN.1 types are
stacked. Specifically, on my first read of that section it seemed that
the EdPrivateKey type took the place of the PrivateKey type in
OneAsymmetricKey. But reading it again now, I can see that the intent of
the section is:

OneAsymmetricKey ::= SEQUENCE {
    ...,
    privateKey PrivateKey(EdPrivateKey(byte sequence))
    ...
}

I think the confusing language is the use of "wrapped in" followed by
"placed in", which implied to me that these were different actions, when
in fact they both refer to the same action of wrapping in OCTET STRING
(resulting in the aforementioned two layers).

Perhaps a clarification in this section might be pertinent? Or maybe I'm
an outlier, and everyone who normally reads these specs will be
completely familiar with the intended usage constraints of ASN.1 types
*shrug*

In any case, thanks for clearing up my confusion! Should I wait around
for consensus on whether the layering is likely to change, or go ahead
with implementing as-is? I don't really want to implement a second
backwards-compatibility handler later ^_^;

Cheers,
str4d

---

From: Nikos Mavrogiannopoulos <[email-masked]>
Date: Mon, 19 Dec 2016 12:37:15 +0100

> Speaking as an individual, yes.  Please don’t change this.

While indeed openssl has quite some user base, version 1.1.0 is still
not being integrated to major distributions to have significant impact.
Do we really need to carry technical debt for that? Can't we change the
OIDs on the final version to avoid confusion with released versions?

regards,
Nikos

---

From: Nikos Mavrogiannopoulos <[email-masked]>
Date: Mon, 19 Dec 2016 12:39:22 +0100

On Fri, 2016-12-16 at 21:26 -0600, Benjamin Kaduk wrote:
> It's a fairly frustrating feeling for a protocol designer to be
> hedged in to a particular behavior because an implementation of a
> draft version escaped into the wild and the change is not worth the
> pain of breaking interoperability. 

In this particular draft (the earlier versions which had been demo'ed
-though not included- in gnutls), we were switching the OIDs once the
definitions were modified in an incompatible way.

regards,
Nikos

---

From: Ilari Liusvaara <[email-masked]>
Date: Mon, 19 Dec 2016 18:41:45 +0200

> OIDs on the final version to avoid confusion with released versions?

Actually, looking at the ECC keys out there, aren't most V2 keys,
since those contain also the public key, as public key is not subset
of private key for ECC (unlike RSA)?

Looking at the private key example in document, those look like
(at least the Ed25519 key does) v1 keys. And I am aware of at least
one Ed25519 implementation (that I didn't write) that requires both
private and public key to load a keypair.

-Ilari

---

From: Jim Schaad <[email-masked]>
Date: Mon, 19 Dec 2016 13:34:10 -0800

In my local version, I have done the following:

1.       Changed EdPrivateKey to CurvePrivateKey.  I hope that this will not cause any confusion with the ECPrivateKey type defined in RFC5915.

2.      I have changed the last sentence in the paragraph mentioned below to
        Thus when encoding a OneAsymmetricKey object, the private key is wrapped in an CurvePrivateKey object and wrapped by the OCTET STRING of the 'privateKey' field.

3.      I have also expanded the appendix with the private key example to have 1) the current PEM format, 2) an ASN.1 dump and 3) the value of the private key. 

I debated using the OKP (Octet Key Pair) which was used in JOSE and COSE but decided not to.

Jim

From: David Benjamin [mailto:[email-masked]] 
Sent: Thursday, December 15, 2016 11:18 PM
To: Jim Schaad <[email-masked]>
Cc: [email-masked]
Subject: Re: [Curdle] Key examples in draft-ietf-curdle-pkix-03

So we don't end up with two variants of this floating around (this thread gives one data point of the current text being misinterpreted), What do you think about these editorial changes?

1. In the paragraph beginning "For the keys defined in this document [...]", add a sentence like "Note the opaque byte sequence is wrapped in OCTET STRINGs twice in total."

2. EdPrivateKey sounds like this only applies to Ed* rather than both Ed* and X*. It should probably be renamed. But the best name I can come up with right now is PrivateKeyWrapper, which is terrible. Another option is to avoid defining a type and just say:

David

On Fri, Dec 16, 2016 at 1:56 AM David Benjamin <[email-masked] <mailto:[email-masked]> > wrote:

Ah, yes, I see OpenSSL has already shipped code which serializes X25519 in this way, as early as OpenSSL 1.1.0 in September. That's unfortunate. It would have been preferable to avoid this confusing double wrapper, but so it goes I guess.

David

On Fri, Dec 16, 2016 at 12:53 AM Jim Schaad <[email-masked] <mailto:[email-masked]> > wrote:

Jim

From: Curdle [mailto:[email-masked] <mailto:[email-masked]> ] On Behalf Of David Benjamin
Sent: Wednesday, December 14, 2016 5:23 AM
To: Ilari Liusvaara <[email-masked] <mailto:[email-masked]> >; str4d <[email-masked] <mailto:[email-masked]> >
Cc: [email-masked] <mailto:[email-masked]> 
Subject: Re: [Curdle] Key examples in draft-ietf-curdle-pkix-03

On Wed, Dec 14, 2016 at 7:15 AM Ilari Liusvaara <mailto:[email-masked] <mailto:[email-masked]> > wrote:

David

_______________________________________________
Curdle mailing list
[email-masked] <mailto:[email-masked]> 
https://www.ietf.org/mailman/listinfo/curdle

---

From: Jim Schaad <[email-masked]>
Date: Mon, 19 Dec 2016 23:09:50 -0800

> -----Original Message-----
> From: Curdle [mailto:[email-masked]] On Behalf Of Ilari Liusvaara
> Sent: Monday, December 19, 2016 8:42 AM
> To: [email-masked]
> > > > I believe that the OpenSSL people would be sad if we changed this
> > > > at this time.  I did some interop testing with their developers
> > > > before the last version was released and the OCTET STRING wrapper
> > > > on the private key is what we were doing at the time.
> > >
> > Do we really need to carry technical debt for that? Can't we change
> > the OIDs on the final version to avoid confusion with released versions?
> 
> Actually, looking at the ECC keys out there, aren't most V2 keys, since those
> contain also the public key, as public key is not subset of private key for ECC
> (unlike RSA)?

Not sure if that is a true statement.  There are two opportunities to have the public key in for ECC.  It can be as part of the PKCS#8 wrapper (or OneAsymmetricKey if you talk RFC 5915) or in the ECPrivateKey structure (RFC 5915).  If part of the OneAsymmetricKey then the version number for that is v2.  If part of the ECPrivateKey then both are v1 structures.

I made the decision that having the public key in two places did not make sense so it is only in the OneAsymmetricKey structure as outlined in this document.  Thus, if the public key is present, yes it would be a v2.
> 
> Looking at the private key example in document, those look like (at least the
> Ed25519 key does) v1 keys. And I am aware of at least one Ed25519
> implementation (that I didn't write) that requires both private and public key to
> load a keypair.

I hope the code verifies that the public and private match.

Jim