Missing documentation for EdDSA key serialization
Anders Rundgren
anders.rundgren.net at gmail.com
Tue Sep 1 02:00:12 UTC 2020
Hi Anthony and Mike,
It is not reversing that is the problem but assumption that you know that:
- Reversing is required.
- XOdd should always(?) be set to false.
EdECPoint is presumably targeting other applications which are closer to the EdDSA core than PKIX and JOSE.
The serialization of EdDSA public keys to RFC 8032 compatible representation is currently is performed by this "experimentally derived" code:
byte[] rawKey = edEcPoint.getY().toByteArray();
while (rawKey.length < ANTICIPATED_LENGTH) {
prepend rawKey with a zero byte
}
if (edEcPoint.isXOdd()) {
rewKey[0] |= 0x80;
}
rawKey = reverse(rawKey);
This is obviously not something you want to have in a professional solution so unfortunately the SubjectPublicKeyInfo route seems to be the only credible way ahead:
https://github.com/cyberphone/openkeystore/blob/427f65df6eb26e9150a1aefd6f0abf3abe761e91/library/src/org/webpki/crypto/CryptoUtil.java#L59
Thanx,
Anders
On 2020-08-31 20:38, Michael StJohns wrote:
> On 8/31/2020 2:00 PM, Anthony Scarpino wrote:
>> On 8/31/20 8:16 AM, Anders Rundgren wrote:
>>> On
>>> https://tools.ietf.org/html/rfc8032#page-24
>>> you can find test vectors that are also used by rfc8037 (JOSE).
>>>
>>> However, there seems to be no information on how to create an EdDSA
>>> public key from such a vector.
>>> Apparently you must be an expert on the inner workings of EdDSA in
>>> order to use this API.
>>>
>>> I have though managed(...) but 1) it looks strange 2) it may be
>>> incorrect.
>>>
>>> Steps
>>> 1. Convert the hex-code to a byte[] array.
>>> 2. Reverse (!) all the bytes in the byte[] array.
>>> 3. publicKey = kf.generatePublic(
>>> new EdECPublicKeySpec(new NamedParameterSpec(alg),
>>> new EdECPoint(false, new
>>> BigInteger(1, theByteArray))));
>>>
>>> Ideally, EdECPoint should have an constructor that does whatever it
>>> takes based on a byte[] array.
>>>
>>> It is equally fuzzy in the other direction. A "getByteArray()" on
>>> EdECPoint had been great.
>>>
>>> Thanx,
>>> Anders
>>
>> Hi,
>>
>> It does seem like a constructor and/or helper methods would be a good
>> addition. I filed a bug to track this:
>>
>> https://bugs.openjdk.java.net/browse/JDK-8252595
>>
>> thanks
>>
>> Tony
>
>
> Generically, maybe this should be added not to the ED based stuff, but
> to BigInteger:
>
> public static BigInteger fromLittleEndianEncoding(int signum, byte[]
> magnitude);
>
> public byte[] getMagnitude(boolean bigEndian, int sizeInBytes); // if
> size in bytes < actual magnitude size, returns the magnitude bytes,
> otherwise returns the magnitude bytes left or right padded to
> sizeInBytes depending on endianness.
>
> Almost all of the crypto stuff related to converting between the various
> encodings of signatures and keys would benefit from a standard version
> of the left/right padding stuff.
>
> Mike
>
> ps - there's a long thread maybe a year or two ago about internal vs
> external representations of the EDDSA and EDDH keys. I'm actually kind
> of surprised that the internal representation turned out to be
> BigInteger. I'm glad it did, but its now kind of strange that we have
> 6 extra interface classes when we could probably have gotten away with
> folding them in under the EC* classes.
>
>
> pps - the alternate way of doing this (and probably the most correct
> way) would be to encode the bytes from the test vector into a
> SubjectPublicKeyInfo public key (see RFC8401) and run that through the
> key factory. That should do all the reversing and generating. You can
> confirm that by doing a getEncoded() on your built public key and
> running it back through the key factory.
>
>
>
More information about the security-dev
mailing list