Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ed25519-dalek: remove ExpandedSecretKey::to_bytes #545

Merged
merged 2 commits into from
Jul 11, 2023

Conversation

tarcieri
Copy link
Contributor

@tarcieri tarcieri commented Jul 2, 2023

The reason ExpandedSecretKey needs a private scalar_bytes field is to retain the canonical scalar bytes as output by SHA-512 during key expansion so they can be serialized by the to_bytes method.

However, ExpandedSecretKeys should not be serialized to the wire.

Removing this method allows the private field to be removed, which allows ExpandedSecretKey to be constructed entirely from public fields. This provides an alternative to #544 for use cases like Ed25519-BIP32 where the private scalar is derived rather than clamped from bytes.

One other change is needed: to_scalar_bytes was changed to to_scalar as the canonical scalar bytes are no longer retained, however this has no impact on its main use case, X25519 Diffie-Hellman exchanges, where the Scalar should NOT be written to the wire anyway.

The reason `ExpandedSecretKey` needs a private `scalar_bytes` field is
to retain the canonical scalar bytes as output by SHA-512 during key
expansion so they can be serialized by the `to_bytes` method.

However, `ExpandedSecretKey`s should not be serialized to the wire.

Removing this method allows the private field to be removed, which
allows `ExpandedSecretKey` to be constructed entirely from public
fields. This provides an alternative to #544 for use cases like
Ed25519-BIP32 where the private scalar is derived rather than clamped
from bytes.

One other change is needed: `to_scalar_bytes` was changed to `to_scalar`
as the canonical scalar bytes are no longer retained, however this has
no impact on its main use case, X25519 Diffie-Hellman exchanges, where
the `Scalar` should NOT be written to the wire anyway.
@tarcieri
Copy link
Contributor Author

tarcieri commented Jul 2, 2023

Note: this is an alternative to both #541 and #544

Comment on lines 22 to 29
assert_eq!(
scalar_a_bytes,
hex!("357c83864f2833cb427a2ef1c00a013cfdff2768d980c0a3a520f006904de90f")
);
assert_eq!(
scalar_b_bytes,
hex!("6ebd9ed75882d52815a97585caf4790a7f6c6b3b7f821c5e259a24b02e502e11")
);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: the rest of the D-H workflow is tested, however I removed checking for a particular scalar serialization here since the Scalar has been pre-clamped at this point.

We could check for the clamped version and make a note of it in a comment.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

@tarcieri
Copy link
Contributor Author

tarcieri commented Jul 2, 2023

Another advantage of this approach is it leaves fewer copies of the secret scalar in memory.

Otherwise every ExpandedSecretKey contains two copies of the secret scalar: one unclamped, one clamped.

@burdges
Copy link
Contributor

burdges commented Jul 2, 2023

As an aside, Ed25519-BIP32 has some serious issues, so really it should not be encouraged. Tor has a similar derivation scheme winds up safer. cc dalek-cryptography/ed25519-dalek#137

@tarcieri
Copy link
Contributor Author

tarcieri commented Jul 2, 2023

@burdges AFAICT this would also work with Tor's method which also uses a computed scalar.

(The point of having this "hazmat" API is so ed25519-dalek can remain agnostic to specific derivation methods while still allowing signatures to be computed with derived keys)

@pinkforest pinkforest mentioned this pull request Jul 5, 2023
@rozbb
Copy link
Contributor

rozbb commented Jul 10, 2023

Copying reasoning from my comment in #544:

The original reason I included scalar_bytes was because section 5.1.5 didn't say you do a modular reduction of the clamped integer when computing the pubkey. So I kept this by the letter of the law.

But this detail doesn't matter! Yes it is true that sometimes s.reduce() * H != s * H, but this is only for H that are not in the prime-order subgroup. The only place scalar_bytes is used (outside of defining scalar) is in the pubkey generation step EdwardsPoint::mul_base_clamped(scalar_bytes). Since the generator is in the prime order subgroup, I should be able to just do scalar * ED25519_BASEPOINT.

Copy link
Contributor

@rozbb rozbb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added my reasoning above. Looks good to me!

Comment on lines 22 to 29
assert_eq!(
scalar_a_bytes,
hex!("357c83864f2833cb427a2ef1c00a013cfdff2768d980c0a3a520f006904de90f")
);
assert_eq!(
scalar_b_bytes,
hex!("6ebd9ed75882d52815a97585caf4790a7f6c6b3b7f821c5e259a24b02e502e11")
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

scalar_b_bytes,
hex!("6ebd9ed75882d52815a97585caf4790a7f6c6b3b7f821c5e259a24b02e502e11")
scalar_b.to_bytes(),
clamp_and_reduce(&Sha512::digest(ed25519_secret_key_b)[..32]),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Manually verified that Sha512::digest matches the hex here. I removed the hex because it didn't come from any test vector. This seems like a more principled way of testing things.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$ echo "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60" | xxd -r -p | shasum -a 512 | head -c 64
357c83864f2833cb427a2ef1c00a013cfdff2768d980c0a3a520f006904de90f⏎
$ echo "4ccd089b28ff96da9db6c346ec114e0f5b8a319f35aba624da8cf6ed4fb8a6fb" | xxd -r -p | shasum -a 512 | head -c 64
6ebd9ed75882d52815a97585caf4790a7f6c6b3b7f821c5e259a24b02e502e11⏎

@rozbb rozbb merged commit 5f0d41f into main Jul 11, 2023
@tarcieri tarcieri deleted the ed25519-dalek/remove-expanded-secret-key-to-bytes branch November 14, 2023 14:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants