Description
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).