Repository navigation
Conversation
The raw Curve25519::eval ladder leaves RFC 7748 scalar clamping to the caller (as Curve25519::dh1 does for generated keys), but the Python reference implementation clamps inside X25519. Identities derived from seed material that is not already clamped — for example deterministic rfed channel identities that use SHA-256(name) directly as the private scalar — therefore produced public keys and Diffie-Hellman shared secrets that disagreed with Python RNS, breaking encryption against Python peers. Clamp the scalar in from_private_bytes. Clamping is idempotent, so generated keys and keys loaded from files written by Python RNS (whose stored scalars are already clamped) are unaffected. Adds a test_crypto interop vector generated by the Python reference pinning public-key derivation, the shared secret, and the Identity::load_private_key path for a seeded identity.
Updated CHANGELOG with cryptography fixes and test additions.
|
Thanks @bergie for the fix, and for generating the vector with the Python reference. I ran the new The contribution policy only accepts crypto changes that fix a demonstrated bug against the reference implementation (section 4), and asks for a way to reproduce (section 5.3). So before this can go further:
If no such seed fails on master, the Crypto fork's Optional hardening while you're in there: check that the key is 32 bytes in My time for reviews is limited, so it may take me a while to come back to this. |
The raw Curve25519::eval ladder leaves RFC 7748 scalar clamping to the caller (as Curve25519::dh1 does for generated keys), but the Python reference implementation clamps inside X25519. Identities derived from seed material that is not already clamped — for example deterministic rfed channel identities that use SHA-256(name) directly as the private scalar — therefore produced public keys and Diffie-Hellman shared secrets that disagreed with Python RNS, breaking encryption against Python peers.
Clamp the scalar in from_private_bytes. Clamping is idempotent, so generated keys and keys loaded from files written by Python RNS (whose stored scalars are already clamped) are unaffected.
Adds a test_crypto interop vector generated by the Python reference pinning public-key derivation, the shared secret, and the Identity::load_private_key path for a seeded identity.