> For the complete documentation index, see [llms.txt](https://docs.zkbob.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.zkbob.com/implementation/transaction-overview/untitled-1/memo-block-encryption.md).

# Memo Block Encryption

The main purpose of the memo block is to publish transaction details. Due to the secret nature of a transaction, the list of admitted users able to access data is strictly restricted. There are two critical data components encrypted in the memo block: an output account and output notes.

Only the transaction sender can access the output account and notes. The output account is used by the sender to maintain the wallet state, and notes are used to retrieve the outgoing history of transactions. The output account should not be available to the transaction receiver. Shared secrets are used to implement this feature.

There are three encrypted entities in the memo block.

* Account Encryption
* Notes Encryption
* Shared Secrets Encryption

### Account Encryption

An output account in the memo block is encrypted with the random key $$key\_a$$ by the symmetric algorithm [ChaCha20Poly1305](https://tools.ietf.org/html/rfc8439):

* Generate a random symmetric 256-bit key: $$key\_a = random()$$
* Encrypt output account: $$acc^{enc} = ChaCha20Poly1305\_{key\_a}^{nonce}(acc)$$

{% hint style="info" %}
Nonce for $$ChaCha20Poly1305$$ is a fixed value. It's the first 12 bytes of the $$keccak256("ZeroPool")$$: `0x5bbdffc6fe73c460f1b2b85d`
{% endhint %}

To decrypt output account user should obtain $$key\_a$$ from the memo block. The transaction sender only can access this key.

### Notes Encryption

Output notes are encrypted with the ephemeral keys. Steps to encrypt a $$Note\_i$$:

* Generate a random 256-bit ephemeral secret key: $$a\_i = random()$$
* Calculate an ephemeral public key for the $$Note\_i$$: $$A\_i = a\_i \text{ToSubGroupHash}\_{E(F\_r)}(Note\_i.d)$$
* Derive a symmetric encryption key for the note: $$key\_i = keccak256(a\_i Note\_i.P\_d)$$
* Encrypt note: $$Note\_i^{enc} = ChaCha20Poly1305\_{key\_i}^{nonce}(Note\_i)$$
* There are two public values for the each note in the memo block: $$A\_i$$ and $$Note\_i^{enc}$$

To decrypt a note the user obtains the corresponding $$key\_i$$. There are two ways to get it:

* to obtain $$key\_i$$ from the shared secrets (a sender case)
* to derive $$key\_i$$ from the $$A\_i$$ and account's key $$\eta$$ (a receiver case): $$key\_i = keccak256(A\_i \eta)$$

### Shared secrets encryption

Shared secrets block contains symmetric keys for account and notes encryption: $$keys = (key\_a, key\_1, key\_2, ...)$$. The following actions are used to encrypt these keys:

* Generate a random 192-bit nonce: $$nonce = random()$$
* Encrypt $$keys$$: $$keys^{enc} = XChaCha20Poly1305\_{\kappa}^{nonce}(keys)$$
* Put $$(nonce, keys^{enc})$$ in the shared secrets block

{% hint style="info" %}
$$keys^{enc}$$ could be decrypted with the $$\kappa$$ key only.
{% endhint %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.zkbob.com/implementation/transaction-overview/untitled-1/memo-block-encryption.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
