Skip to main content

encrypt-and-tag

Encrypt and tag an incoming message

Bob wants to send Alice a private message, e.g. the contents of a note, which we'll refer to as the plaintext\plaintext. Bob and Alice are using a "tag hopping" scheme to help with note discovery. Let's assume they've already handshaked to establish a shared secret Sm,taggingBobAlice\sharedsecret_{m,tagging}^{Bob \rightarrow Alice}, from which a sequence of tags tagm,iBobAlice\tagg_{m,i}^{Bob \rightarrow Alice} can be derived.

ThingDerivationNameComments
d\dGiven by Alice(Diversifier)Remember, in most cases, d=1\d=1 is sufficient.
Gd\GddG\d \cdot G(Diversified) generatorRemember, when d=1\d = 1, Gd=G\Gd = G.
eskheader\eskheaderrandF\stackrel{rand}{\leftarrow} \mathbb{F}ephemeral secret key
Epkd,header\EpkdheadereskheaderGd\eskheader \cdot \Gd(Diversified) Ephemeral public key
Sm,header\sharedsecret_{m,header}eskheaderIvpkm\esk_{header} \cdot \IvpkmShared secret, for ciphertext header encryptionTODO: can we use the same ephemeral keypair for both the ciphertext header and the ciphertext?
TODO: diversify the Ivpkm\Ivpkm?
hm,enc,header\hmencheaderh("?", Sm,header\sharedsecret_{m,header})Ciphertext header encryption key
ciphertext_header\ciphertextheaderenchm,enc,headerIvpkmenc^{\Ivpkm}_{\hmencheader}(app_address)Ciphertext header
esk\eskrandF\stackrel{rand}{\leftarrow} \mathbb{F}ephemeral secret key
Epkd\EpkdeskGd\esk \cdot \Gd(Diversified) Ephemeral public key
Sapp,enc\sharedsecret_{app,enc}eskIvpkapp,d,stealth\esk \cdot \IvpkdstealthShared secret, for ciphertext encryption
happ,enc\happench("?", Sapp,enc\sharedsecret_{app,enc})Incoming data encryption key
ciphertext\ciphertextenchapp,encIvpkapp,d,stealth(plaintext)enc^{\Ivpkdstealth}_{\happenc}(\plaintext)Ciphertext
payload\payload[tagm,iBobAlice\tagg_{m, i}^{Bob \rightarrow Alice}, ciphertext_header\ciphertextheader, ciphertext\ciphertext, Epkd,header\Epkdheader, Epkd\Epkd]Payload

Alice can learn about her new payload\payload as follows. First, she would identify the transaction has intended for her, either by observing tagm,iBobAlice\tagg_{m, i}^{Bob \rightarrow Alice} on-chain herself (and then downloading the rest of the payload which accompanies the tag), or by making a privacy-preserving request to a server, to retrieve the payload which accompanies the tag. Assuming the payload\payload has been identified as Alice's, and retrieved by Alice, we proceed.

Given that the tag in this illustration was derived from Alice's master key, the tag itself doesn't convey which app_address to use, to derive the correct app-siloed incoming viewing secret key that would enable decryption of the ciphertext. So first Alice needs to decrypt the ciphertext_header\ciphertextheader using her master key:

ThingDerivationName
Sm,header\sharedsecret_{m,header}ivskmEpkd,header\ivskm \cdot \EpkdheaderShared secret, for encrypting the ciphertext header
hm,enc,header\hmencheaderh("?", Sm,header\sharedsecret_{m,header})Incoming encryption key
app_addressdecrypthm,enc,headerivskm(ciphertext_header)decrypt_{\hmencheader}^{\ivskm}(\ciphertextheader)App address
ivskstealth\ivskstealthSee derivations above. Use the decrypted app_address.Incoming viewing secret key
Sapp,enc\sharedsecret_{app, enc}ivskstealthEpkd\ivskstealth \cdot \EpkdShared secret, for ciphertext encryption
happ,enc\happench("?", Sapp,enc\sharedsecret_{app, enc})Ciphertext encryption key
plaintext\plaintextdecrypthapp,encivskstealth(ciphertext)decrypt_{\happenc}^{\ivskstealth}(\ciphertext)Plaintext

Encrypt and tag an outgoing message

Bob wants to send himself a private message (e.g. a record of the outgoing notes that he's created for other people) which we'll refer to as the plaintext\plaintext. Let's assume Bob has derived a sequence of tags tagm,iBobAlice\tagg_{m,i}^{Bob \rightarrow Alice} for himself (see earlier).

Note: this illustration uses master keys for tags, rather than app-specific keys for tags. App-specific keys for tags could be used instead, in which case a 'ciphertext header' wouldn't be needed for the 'app_address', since the address could be inferred from the tag.

Note: rather than copying the 'shared secret' approach of Bob sending to Alice, we can cut a corner (because Bob is the sender and recipient, and so knows his own secrets).

Note: if Bob has sent a private message to Alice, and he also wants to send himself a corresponding message:

  • he can likely re-use the ephemeral keypairs for himself.
  • he can include esk\esk in the plaintext that he sends to himself, as a way of reducing the size of his ciphertext\ciphertext (since the esk\esk will enable him to access all the information in the ciphertext that was sent to Alice).

Note: the violet symbols should actually be orange here.

ThingDerivationNameComments
d\dGiven by Alice(Diversifier)Remember, in most cases, d=1\d=1 is sufficient.
Gd\GddG\d \cdot G(Diversified) generatorRemember, when d=1\d = 1, Gd=G\Gd = G.
eskheader\eskheaderrandF\stackrel{rand}{\leftarrow} \mathbb{F}ephemeral secret key
Epkd,header\EpkdheadereskheaderGd\eskheader \cdot \Gd(Diversified) Ephemeral public key
hm,enc,header\hmencheaderh("?", ovskm\ovskm, Epkd,header\Epkdheader)Header encryption keyThis uses a master secret key ovskm\ovskm, which MUST NOT be given to an app nor to an app circuit. However, it can still be given to a trusted precompile, which can handle this derivation securely.
ciphertext_header\ciphertextheaderenchm,enc,headerenc_{\hmencheader}(app_address)Ciphertext header encryption key
esk\eskrandF\stackrel{rand}{\leftarrow} \mathbb{F}ephemeral secret key
Epkd\EpkdeskGd\esk \cdot \Gd(Diversified) Ephemeral public key
happ,enc\happench("?", ovskapp\ovskapp, Epkd\Epkd)Outgoing data encryption keySince ovskapp\ovskapp is a hardened app-siloed secret key, it may be safely given to the dapp or passed into the app's circuit.
ciphertext\ciphertextenchapp,enc(plaintext)enc_{\happenc}(\plaintext)Ciphertext
payload\payload[tagm,iBobBob\tagg_{m, i}^{Bob \rightarrow Bob}, ciphertext_header\ciphertextheader, ciphertext\ciphertext, Epkd,header\Epkdheader, Epkd\Epkd]Payload

Alice can learn about her new payload\payload as follows. First, she would identify the transaction has intended for her, either by observing tagm,iBobAlice\tagg_{m, i}^{Bob \rightarrow Alice} on-chain herself (and then downloading the rest of the payload which accompanies the tag), or by making a privacy-preserving request to a server, to retrieve the payload which accompanies the tag. Assuming the payload\payload has been identified as Alice's, and retrieved by Alice, we proceed.

Given that the tag in this illustration was derived from Alice's master key, the tag itself doesn't convey which app_address to use, to derive the correct app-siloed incoming viewing secret key that would enable decryption of the ciphertext. So first Alice needs to decrypt the ciphertext_header\ciphertextheader using her master key:

ThingDerivationName
hm,enc,header\hmencheaderh("?", ovskm\ovskm, Epkd,header\Epkdheader)
app_addressdecrypthm,enc,header(ciphertext_header)decrypt_{\hmencheader}(\ciphertextheader)
ovskapp\ovskappSee derivations above. Use the decrypted app_address.
happ,enc\happench("?", ovskm\ovskm, Epkd\Epkd)
plaintext\plaintextdecrypthapp,enc(ciphertext)decrypt_{\happenc}(\ciphertext)

Doing this inside an app circuit

Here's how an app circuit could constrain the app-siloed outgoing viewing secret key (ovskapp\ovskapp) to be correct:

The app circuit exposes, as public inputs, an "outgoing viewing key validation request":

ThingDerivationNameComments
outgoing_viewing_key_validation_requestapp_address: app_address,
hardened_child_sk: nskapp\nskapp,
claimed_parent_pk: Npkm\Npkm

The kernel circuit can then validate the request (having been given ovskm\ovskm as a private input to the kernel circuit):

ThingDerivationNameComments
ovskapp\ovskapph(ovskm,app_address)h(\ovskm, \text{app\_address})
Ovpkm\OvpkmovskmG\ovskm \cdot GOutgoing viewing public key
Copy-constrain ovskm\ovskm with ovskm\ovskm.

If the kernel circuit succeeds in these calculations, then the ovskapp\ovskapp has been validated as the correct app-siled secret key for Ovpkm\Ovpkm.

Encrypt and tag an internal incoming message

Internal incoming messages are handled analogously to outgoing messages, since in both cases the sender is the same as the recipient, who has access to the secret keys when encrypting and tagging the message.