Skip to content

Convert Ed25519 to Curve25519 keys #5557

Open
@chrysn

Description

@chrysn

Keys generally used for signing can be also used for derivation of a shared secret -- they have to be converted from the Twisted Edwards to the Montgomery form for that, though.

One application for this is OSCORE group communication, where keys that are mostly used for signing are used for static-static key derivation (https://tools.ietf.org/html/draft-ietf-core-oscore-groupcomm-10#section-2.3.1 the paragraph starting "If EdDSA asymmetric keys are used,").

It would be nice to have that functionality in cryptography.

Right now I can perform most steps of this using the cryptography module, but the coordinate conversion process is not available, and as a workaround I'm reaching into the NaCl library just to do that. Example code:

from cryptography.hazmat.primitives.asymmetric import x25519
from cryptography.hazmat.primitives.asymmetric import ed25519
import nacl.signing, nacl.public

private1 = bytes.fromhex('397CEB5A8D21D74A9258C20C33FC45AB152B02CF479B2E3081285F77454CF347')
private2 = bytes.fromhex('70559B9EECDC578D5FC2CA37F9969630029F1592AFF3306392AB15546C6A184A')
shared_reference = bytes.fromhex('4546babdb9482396c167af11d21953bfa49eb9f630c45de93ee4d3b9ef059576')


# These keys would regularly be used like this:
cpriv1 = ed25519.Ed25519PrivateKey.from_private_bytes(private1)

# Importing the key in NaCl
npriv1 = nacl.signing.SigningKey(seed=private1, encoder=nacl.encoding.RawEncoder)
npriv2 = nacl.signing.SigningKey(seed=private2, encoder=nacl.encoding.RawEncoder)

# Use NaCl to convet to Montgomery form
npriv1_mont = npriv1.to_curve25519_private_key()
npriv2_mont = npriv2.to_curve25519_private_key()

# Import the converted keys back into Cryptography
k1 = x25519.X25519PrivateKey.from_private_bytes(npriv1_mont._private_key)
k2 = x25519.X25519PrivateKey.from_private_bytes(npriv2_mont._private_key)
shared_1_2 = k1.exchange(k2.public_key())
shared_2_1 = k2.exchange(k1.public_key())
assert shared_1_2 == shared_2_1
assert shared_1_2 == shared_reference

(Keys and reference value stem from the test vectors used during the IETF hackathon)

If a conversion function existed, the NaCl code could bre replaced with

k1 = cpriv1.to_x25519()

where the to_x25519 documentation would say something like:

Converts the Ed25519 key (which is a point on the Edwards curve) to a key usable for X25519 key exchanges (and thus a point on the Montgomery curve).

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions