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

crypto_box: fix Scalar conversion to SecretKey #137

Merged
merged 3 commits into from
Aug 17, 2023

Conversation

tarcieri
Copy link
Member

Avoids round tripping Scalar to/from bytes when leveraging the From<Scalar> impl for SecretKey.

Avoids round tripping `Scalar` to/from bytes when leveraging the
`From<Scalar>` impl for `SecretKey`.
@tarcieri
Copy link
Member Author

@dignifiedquire can you give this a try and see if it fixes the problem you were encountering in dalek-cryptography/curve25519-dalek#564 ?

@dignifiedquire
Copy link
Member

Can confirm, fixes all the issues I have been seeing

@rozbb
Copy link

rozbb commented Aug 17, 2023

To give context, this addresses a compatibility bug with ed25519. A crypto_box::SecretKey had an impl From<Scalar>, which converted it to bytes and saved it. To compute the corresponding verifying key, it clamped the bytes and multiplied by the base point. The incompatibility is

  1. To compute a pubkey in Ed25519, you compute the unreduced secret bytes, clamp it, and multiply it by the base point
  2. To compute a pubkey in crypto_box from a scalar, you take the reduced secret bytes (ie the scalar), clamp it, and multiply by the base point

These two procedures will result in different public keys. The solution here is to: 1) assume that the given scalar is already clamped and 2) save the original secret bytes.

Question: does the new From<Scalar> impl do the right thing? It sets bytes = scalar.to_bytes(). But if you feed that back into SecretKey::from_bytes will you actually get the same scalar? It seems like the answer should be no

@tarcieri
Copy link
Member Author

tarcieri commented Aug 17, 2023

@rozbb to_bytes will produce the clamped scalar in the event the From<Scalar> impl is used.

I'm not sure how to solve that except by removing either the From<Scalar> impl or the to_bytes method, either of which is a breaking change.

Alternatively we can add some documentation about this to the to_bytes method.

@rozbb
Copy link

rozbb commented Aug 17, 2023

Removing From<Scalar> would probably be the most sound option if the priority is compatibility with Ed25519 (Ed doesn’t define secret keys as scalars). But if people really want it, I think loud warnings about the non-idempotence of the round trip might suffice

@dignifiedquire
Copy link
Member

Removing From<Scalar> would probably be the most sound option

How would I go about creating the matching secret key then from the ed25519 key?

@rozbb
Copy link

rozbb commented Aug 17, 2023

One possibility is it takes the ed25519 secret key and computes the scalar bytes itself, ie impl From<[0u8; 32]> computes SHA512(bytes)[..32]

@dignifiedquire
Copy link
Member

dignifiedquire commented Aug 17, 2023

One possibility is it takes the ed25519 secret key and computes the scalar bytes itself, ie impl From<[0u8; 32]> computes SHA512(bytes)[..32]

But that sounds to me even more error prone than having these helper functions. Honestly I still think the cleanest and safest way would be to have a feature on ed25519 called crypto-box that does the type safe conversion, as this would be much easier to ensure all invariants are upheld, than using the different raw point formats.

@tarcieri
Copy link
Member Author

I've been really hoping to avoid directly coupling crypto_box with anything Ed25519-related

@tarcieri
Copy link
Member Author

I went ahead and added some notes in 6195d3a.

If anyone feels particularly strongly about trying to find a better solution to this, I'd suggest opening a follow-up issue.

@tarcieri tarcieri merged commit 5a63c09 into master Aug 17, 2023
@tarcieri tarcieri deleted the crypto_box/fix-scalar-conversion branch August 17, 2023 15:01
@tarcieri tarcieri mentioned this pull request Aug 17, 2023
github-merge-queue bot pushed a commit to n0-computer/iroh that referenced this pull request Aug 21, 2023
## Description

Moves all keys being used to `ed25519` keys, and only converts them to
`crypto_box` keys only when needed.

### Breaking Changes

- This is a breaking change to the derp protocol, as now only `ed25519`
keys are sent over the wire.
- The encrypted packets also changed, as first the sealed message and
then the nonce is now sent
- All configs and cli options now use `secret_key` not `keypair` or
`private_key`
- MSRV from `1.66` to `1.67` due to updated dependencies
- `PeerId` is removed in favor of just using `PublicKey` directly
 
## Notes & open questions

- [x] This is more expensive as the conversions are not cached at the
moment, we should do so either in this PR or in a follow up.
- [x] Depends on RustCrypto/nacl-compat#137 as
otherwise the upgrade of `ed25519` breaks the code.

## Caching

There is a performance benefit to caching, so for public key we always
cache the `crypto_box::PublicKey`, and for `SecretKey`s we cache using
`OnceCell`.

---------

Co-authored-by: Diva M <[email protected]>
rklaehn pushed a commit to n0-computer/iroh-blobs that referenced this pull request Oct 22, 2024
## Description

Moves all keys being used to `ed25519` keys, and only converts them to
`crypto_box` keys only when needed.

### Breaking Changes

- This is a breaking change to the derp protocol, as now only `ed25519`
keys are sent over the wire.
- The encrypted packets also changed, as first the sealed message and
then the nonce is now sent
- All configs and cli options now use `secret_key` not `keypair` or
`private_key`
- MSRV from `1.66` to `1.67` due to updated dependencies
- `PeerId` is removed in favor of just using `PublicKey` directly
 
## Notes & open questions

- [x] This is more expensive as the conversions are not cached at the
moment, we should do so either in this PR or in a follow up.
- [x] Depends on RustCrypto/nacl-compat#137 as
otherwise the upgrade of `ed25519` breaks the code.

## Caching

There is a performance benefit to caching, so for public key we always
cache the `crypto_box::PublicKey`, and for `SecretKey`s we cache using
`OnceCell`.

---------

Co-authored-by: Diva M <[email protected]>
rklaehn pushed a commit to n0-computer/iroh-blobs that referenced this pull request Oct 22, 2024
## Description

Moves all keys being used to `ed25519` keys, and only converts them to
`crypto_box` keys only when needed.

### Breaking Changes

- This is a breaking change to the derp protocol, as now only `ed25519`
keys are sent over the wire.
- The encrypted packets also changed, as first the sealed message and
then the nonce is now sent
- All configs and cli options now use `secret_key` not `keypair` or
`private_key`
- MSRV from `1.66` to `1.67` due to updated dependencies
- `PeerId` is removed in favor of just using `PublicKey` directly
 
## Notes & open questions

- [x] This is more expensive as the conversions are not cached at the
moment, we should do so either in this PR or in a follow up.
- [x] Depends on RustCrypto/nacl-compat#137 as
otherwise the upgrade of `ed25519` breaks the code.

## Caching

There is a performance benefit to caching, so for public key we always
cache the `crypto_box::PublicKey`, and for `SecretKey`s we cache using
`OnceCell`.

---------

Co-authored-by: Diva M <[email protected]>
matheus23 pushed a commit to n0-computer/iroh-doctor that referenced this pull request Oct 22, 2024
## Description

Moves all keys being used to `ed25519` keys, and only converts them to
`crypto_box` keys only when needed.

### Breaking Changes

- This is a breaking change to the derp protocol, as now only `ed25519`
keys are sent over the wire.
- The encrypted packets also changed, as first the sealed message and
then the nonce is now sent
- All configs and cli options now use `secret_key` not `keypair` or
`private_key`
- MSRV from `1.66` to `1.67` due to updated dependencies
- `PeerId` is removed in favor of just using `PublicKey` directly
 
## Notes & open questions

- [x] This is more expensive as the conversions are not cached at the
moment, we should do so either in this PR or in a follow up.
- [x] Depends on RustCrypto/nacl-compat#137 as
otherwise the upgrade of `ed25519` breaks the code.

## Caching

There is a performance benefit to caching, so for public key we always
cache the `crypto_box::PublicKey`, and for `SecretKey`s we cache using
`OnceCell`.

---------

Co-authored-by: Diva M <[email protected]>
dignifiedquire added a commit to n0-computer/iroh-gossip that referenced this pull request Oct 23, 2024
## Description

Moves all keys being used to `ed25519` keys, and only converts them to
`crypto_box` keys only when needed.

### Breaking Changes

- This is a breaking change to the derp protocol, as now only `ed25519`
keys are sent over the wire.
- The encrypted packets also changed, as first the sealed message and
then the nonce is now sent
- All configs and cli options now use `secret_key` not `keypair` or
`private_key`
- MSRV from `1.66` to `1.67` due to updated dependencies
- `PeerId` is removed in favor of just using `PublicKey` directly
 
## Notes & open questions

- [x] This is more expensive as the conversions are not cached at the
moment, we should do so either in this PR or in a follow up.
- [x] Depends on RustCrypto/nacl-compat#137 as
otherwise the upgrade of `ed25519` breaks the code.

## Caching

There is a performance benefit to caching, so for public key we always
cache the `crypto_box::PublicKey`, and for `SecretKey`s we cache using
`OnceCell`.

---------

Co-authored-by: Diva M <[email protected]>
matheus23 pushed a commit to n0-computer/iroh that referenced this pull request Nov 14, 2024
## Description

Moves all keys being used to `ed25519` keys, and only converts them to
`crypto_box` keys only when needed.

### Breaking Changes

- This is a breaking change to the derp protocol, as now only `ed25519`
keys are sent over the wire.
- The encrypted packets also changed, as first the sealed message and
then the nonce is now sent
- All configs and cli options now use `secret_key` not `keypair` or
`private_key`
- MSRV from `1.66` to `1.67` due to updated dependencies
- `PeerId` is removed in favor of just using `PublicKey` directly
 
## Notes & open questions

- [x] This is more expensive as the conversions are not cached at the
moment, we should do so either in this PR or in a follow up.
- [x] Depends on RustCrypto/nacl-compat#137 as
otherwise the upgrade of `ed25519` breaks the code.

## Caching

There is a performance benefit to caching, so for public key we always
cache the `crypto_box::PublicKey`, and for `SecretKey`s we cache using
`OnceCell`.

---------

Co-authored-by: Diva M <[email protected]>
dignifiedquire added a commit to n0-computer/iroh-metrics that referenced this pull request Dec 2, 2024
## Description

Moves all keys being used to `ed25519` keys, and only converts them to
`crypto_box` keys only when needed.

### Breaking Changes

- This is a breaking change to the derp protocol, as now only `ed25519`
keys are sent over the wire.
- The encrypted packets also changed, as first the sealed message and
then the nonce is now sent
- All configs and cli options now use `secret_key` not `keypair` or
`private_key`
- MSRV from `1.66` to `1.67` due to updated dependencies
- `PeerId` is removed in favor of just using `PublicKey` directly
 
## Notes & open questions

- [x] This is more expensive as the conversions are not cached at the
moment, we should do so either in this PR or in a follow up.
- [x] Depends on RustCrypto/nacl-compat#137 as
otherwise the upgrade of `ed25519` breaks the code.

## Caching

There is a performance benefit to caching, so for public key we always
cache the `crypto_box::PublicKey`, and for `SecretKey`s we cache using
`OnceCell`.

---------

Co-authored-by: Diva M <[email protected]>
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