Skip to content

Store decryption keys in the client #1613

@mmagician

Description

@mmagician

As we move to encrypting the notes sent over the transport layer, we need to support decryption in miden-client. Specifically, we need to:

  1. Generate a new key pair
  2. Store the decryption key in some key store
  3. Share the encryption key as part of Address that we give out
  4. Trial decrypt the notes fetched from the transport layer

And each comes with its own set of questions.

Generate a new key pair

Main questions:

  1. How many key pairs and how to associated them to the accounts?
    1. one key pair per client instance,
    2. one key pair per account,
    3. or let users arbitrarily choose the association?
  2. Based on the answer to the above, is the key automatically generated? If so, when?

My opinionated answer:
I think 1.iii is too complex and we can safely discard this option.
1.i is easy to manage for the client, but it does reduce privacy slightly. Consider the following scenario:

  • user generates two accounts, and wishes to receive payments from two separate parties A & B
  • the NoteTag derived for each account is unique
  • but when sharing their Address, the RoutingParameters will include the same encryption key when shared with both A & B
  • while neither A, B, nor the transport layer can correlate the note ciphertext, A & B can collude to figure out they are sending to the same user (since the encryption key is the same)
    With 1.i, the key is automatically generated upon client instantiation (if not present already).

1.ii does not suffer the same problem as 1.i, and I think it doesn't introduce much more complexity for the client: a key is automatically generated when the user requests a new account.
We can easily track (in the DB) which key corresponds to which AccountId / Address.

Store the decryption key

Once we have the answer to the above, the mechanics become straightforward.
The design question is whether we repurpose the existing {Filesystem/Web}Keystore (e.g. with a new trait e.g. EncryptionStore), or develop a fresh place to store encryption keys separately from signing keys.

Share the encryption key

Sharing the encryption key should be done via Address struct, which encodes the key as part of the RoutingParameters. The question is more for the UX / frontend side: how does the user decide whether to share an Address with or without the RoutingParameters?

  • programmatically this could be easy, and I can see how this would be done in the wallet connector that we use e.g. for the faucet: the faucet frontend requests a encryption-ready Address variant.
  • manually we need a clean way to not confuse the user yet still expose the relevant options cc @dagarcia7

Trial decrypt

I think this one is the easiest. The only question is whether we try all notes with all the decryption keys (if there are many)? Or do we have a smart way of associating which note should be decrypted with which key?

  • @v0-e suggests to do the mapping of fetched tag -> respective owned Address, and try the private key of that Address only.

This will be partially informed by the decisions of how we generate and store decryption keys.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions