"Pluggable" key serialization in JCE/JCA

Anders Rundgren anders.rundgren.net at gmail.com
Fri Mar 25 16:33:38 UTC 2022


On 2022-03-25 17:12, Anthony Scarpino wrote:
> When you say "construct and EC key", do you mean creating an EC key from
> an existing set of values via PKCS8 or X509 encoding?  Or are you
> talking about EC key generation?

I was talking about creating keys from parameter data supplied by for example JOSE:
   {
     "kty": "EC",
     "crv": "P-256",
     "x": "6BKxpty8cI-exDzCkh-goU6dXq3MbcY0cd1LaAxiNrU",
     "y": "mCbcvUzm44j3Lt2b5BPyQloQ91tf2D2V-gzeUxWaUdg"
   }

Apparently this particular issue have solution (as Michael StJohns showed), although it is not particularity intuitive as well as undocumented.

Another take on this issue:
https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/security/Key.html#getEncoded()
"Returns the key in its primary encoding format, or null if this key does not support encoding"

With COSE/JOSE there is no longer an obvious primary encoding format.

Anders

> 
> Tony
> 
> On 3/25/22 1:03 AM, Anders Rundgren wrote:
>> Hi Mike & the JDK crypto team,
>>
>> What I'm saying is that key serialization in Java haven't gotten enough
>> attention.  Examples:
>>
>> AFAIK, there is still no support for using named curves to construct an
>> EC key.  Names curves are MANDATORY in JOSE/CODE.
>>
>> The gap between EdDSA keys as expressed in JOSE/COSE and the Java API is
>> simply put GIGANTIC:
>> https://mail.openjdk.java.net/pipermail/security-dev/2020-August/022379.html
>>
>> The only obvious solution is rolling your own:
>> https://github.com/cyberphone/openkeystore/blob/master/library/src/org/webpki/crypto/OkpSupport.java
>>
>> This code [probably] stinks but it is hardly my fault...
>>
>> The JDK crypto team is the only party who can clean up this mess.
>>
>> Since importing X.509 certificates through PKCS12/KeyStore works out of
>> the box without any a prior knowledge of key algorithms, there is
>> already a precedent.  It is almost just copy and paste :)
>>
>> The new crypto systems that are on the way in (BLS, Post Quantum),
>> accentuates this issue.
>>
>> Regarding HSMs, I gave it one more thought and I didn't come up with any
>> connections except maybe in Keytool but HSMs appear to be X.509-oriented
>> which not the case with COSE/JOSE.
>>
>> Regards,
>> Anders
>>
>> On 2022-03-25 3:12, Michael StJohns wrote:
>>> On 3/24/2022 12:28 PM, Anders Rundgren wrote:
>>>> On 2022-03-24 16:59, Michael StJohns wrote:
>>>>> On 3/24/2022 2:46 AM, Anders Rundgren wrote:
>>>>>> Hi List,
>>>>>>
>>>>>> I find it a bit strange that every user of crypto either have to write
>>>>>> or install specific software for converting JOSE/COSE/PEM keys
>>>>>> back-and-forth to Java's internal representation. This reduces the
>>>>>> value of the abstract types as well.
>>>>>>
>>>>>> Now there is whole bunch of new algorithms coming to the Java platform
>>>>>> making this task even less attractive.
>>>>>>
>>>>>> So my question is simply: How about including this part in an enhanced
>>>>>> JCE/JCA?  That is, making the encoder/decoder "pluggable" and hiding
>>>>>> this complexity from users and library developers?
>>>>>
>>>>> Hi Anders -
>>>>
>>>> Hi Mike,
>>>>
>>>>>
>>>>> Isn't that the exact purpose for KeyFactory and its plugins?
>>>>
>>>> They presume that you know not only the key algorithm but the
>>>> associated parameters as well.  Why should users or library developers
>>>> have to deal with that?
>>>
>>> Um - no.  They presume you know the key algorithm, but (using EC Public
>>> keys for example), you can use either of the X509PublicKeySpec (to
>>> decode an encoded key), or the ECPublicKeySpec (to deal with building a
>>> key from scratch using the parameters.  You can notionally (haven't
>>> tried it, but should work) use KeyFactory.getKeySpec() to convert
>>> between the two formats or use Key.getEncoded() to get the default
>>> encoding for the key.
>>>
>>> The equivalent on the ECPrivateKey side are the ECPrivateKeySpec and
>>> PKCS8EncodedKeySpec clases.
>>>
>>> PEM is actually not an encoding, but a wrapping of an encoding. The only
>>> part of Java that deals with it natively (I believe) is the
>>> CertificateFactory for X.509 certificates.  You may have an extra step
>>> to add or remove a PEM style envelope (or the equivalent BASE64 bare
>>> string), but that's reasonable.
>>>
>>>>
>>>> The requirement to know key algorithm in advance forces you into ASN.1
>>>> decoding for dealing with PEMs.  Been there done that.
>>>
>>> Ah - not sure why you wouldn't know the key algorithm, BUT:  It should
>>> theoretically be possible to write a KeyFactory provider that does that
>>> decoding for you from the X509PublicKeySpec (or PKCS8PrivateKeySpec) and
>>> returns an appropriate PublicKey. Check the actual return type to figure
>>> out what type of key.  E.g.:
>>>
>>> KeyFactory kf = KeyFactory.getInstance("GenericDecoder");
>>>
>>> As I said below, you'll need to define the equivalent opaque format
>>> KeySpec classes to handle COSE and JOSE.  I think that's a class per
>>> type of encoding.
>>>
>>>>
>>>>>
>>>>> You might need to add KeySpec types for Jose and Cose
>>>>> (JOSEEncodedKeySpec and COSEEncodedKeySpec) assuming both of those
>>>>> cover
>>>>> all of the secret, public and private key specifications.
>>>>>
>>>>> Or hmm... GenericEncodedKeySpec (String alg, byte[] encoded key) or
>>>>> GenericEncodedKeySpec (String alg, String encodedKey).
>>>>>
>>>>>
>>>>>>
>>>>>> Eventually you could end up with something like:
>>>>>>
>>>>>> PrivateKey privateKey = new KeyConverter().readPrivateKey(byte[] or
>>>>>> stream);
>>>>>>
>>>>>> You would not even have to know in which format the key is supplied in
>>>>>> since this could be accomplished by simple "sniffing".
>>>>>
>>>>> Nope.  This isn't safe as someone might up with yet another
>>>>> representation that looks like one of the "sniffable" ones.  You could
>>>>> build a private implementation that takes its best shot, but ....
>>>>
>>>> Finding out if the container is COSE, JOSE, or PEM is (AFAICT)
>>>> trivial.  If the guess is incorrect a properly designed decoder should
>>>> simply fail.
>>>
>>> It's trivial NOW because its a closed set of possibilities.  And even
>>> then, you're assuming you don't have to detect ASN1 vs raw key encodings
>>> vs string encodings.  Simply detecting a) whether a file is character,
>>> b) detecting the character encoding, and c) accidentally thinking a
>>> character file is actually binary or vice versa is fragile.
>>>
>>> The addition of the "new" EC variant keys required a substantial
>>> reworking of the API to support them and the arguments were fierce.  The
>>> additions were not free.
>>>
>>> I deal with no fewer than 3 encodings for an EC public key.  Two or
>>> three for an EC private key. 2 or 3 text versions of a RSA public key
>>> along with the X509Encoded  binary version and the TPM binary version.
>>> Etc.  I usually know what type of key I'm dealing with when I get it,
>>> but I would love a magic DWIM class that did the right thing on all
>>> inputs.
>>>
>>>
>>>>
>>>>>
>>>>>>
>>>>>> To make "pluggability" feasible, I'm trying to convince the JOSE/COSE
>>>>>> folks to give each new crypto system a separate namespace as an
>>>>>> alternative to overloading OKP (RFC 8037), even if the parameters
>>>>>> match technically.  AFAICT, X.509 public keys essentially already
>>>>>> adhere to this notion.
>>>>>>
>>>>>> I would exclude private key import and export in HSMs since these are
>>>>>> specific and rare occasions.
>>>>>
>>>>> Again, no.  Don't do this in an incomplete way - it will come back to
>>>>> bite you.  You don't have to implement the plugin that talks to the
>>>>> HSM,
>>>>> but you have to define the mechanism/API so that the HSM vendors don't
>>>>> curse your first born child later.
>>>>
>>>>
>>>> This is little bit out of my league but targeting the masses is core.
>>>
>>> This is the problem with open source some times. It may be core, but it
>>> is not complete and leaving this as a problem to be worked later is a
>>> bit unprofessional.
>>>
>>> I don't mean any offense here, but there's a problem with basing
>>> everything what IOT requires and ignoring everything else.
>>>
>>> Later, Mike
>>>
>>>
>>>>
>>>>
>>>> Anders
>>>>
>>>>>
>>>>> Mike
>>>>>
>>>>>
>>>>>>
>>>>>> WDYT?
>>>>>>
>>>>>> Thanx,
>>>>>> Anders
>>>>>
>>>>>
>>>>
>>>
>>




More information about the security-dev mailing list