# ML-KEM Encryption for Backups

<mark style="color:red;">**Backup Encryption Workflow (ML-KEM)**</mark>

#### **Step 1: Data Preparation**

* **Input**: Wallet data (accounts, keys, metadata) is serialized into a JSON string.
* **Hashing**: A SHA-256 hash of the JSON string is generated for integrity checks.
* **Serialization**: Data is converted to a **`Buffer`** for encryption.

#### **Step 2: ML-KEM Encryption**

* **Key Encapsulation**:
  * The recipient’s **ML-KEM public key** (stored in **`account.encryptionPublicKey`**) generates a shared secret.
  * ML-KEM’s **`encapsulate()`** function creates:
    * **Ciphertext**: Encapsulated shared secret (sent to the server).
    * **Shared Secret**: Used for symmetric encryption.
* **Symmetric Encryption**:
  * The shared secret encrypts the backup data using **XSalsa20** (or **AES-256**) for efficiency.
  * Result: A hybrid ciphertext (**`encryptedPayload`**) containing both ML-KEM ciphertext and symmetrically encrypted data.

#### **Step 3: Signature Generation (SLH-DSA)**

* **Hashing the Payload**:
  * The encrypted payload is hashed using Keccak-256 to create a fixed-size digest.
* **SLH-DSA Signing**:
  * The hash is signed using the user’s **SLH-DSA private key** (derived from their mnemonic).
  * Produces a **49,856-byte signature** for tamper-proof verification.

#### **Step 4: Cloud Storage**

* **Payload Structure**:

  ```json
  {
    "signature": "0x...", // 49,856-byte SLH-DSA signature
    "payload": "0x..."    // ML-KEM ciphertext + symmetrically encrypted data
  }
  ```
* **Server-Side Handling**:

  * Backups are stored under the user’s public key (**`account.publicKey`**).
  * The server uses SHA-256 to hash the public key for secure storage.

<mark style="color:red;">**Backup Verification:**</mark>

The server performs **security checks** before allowing access:

#### **Check 1: SLH-DSA Signature Validation**

* **Message Reconstruction**:
  * The server generates valid messages based on timestamps (e.g., **`pubkey-GET-BACKUPS-2023-09-01`**).

```tsx
const legitMessages = [  
  `${pubkey}-GET-BACKUPS-${ymdnow}`,  
  `${pubkey}-GET-BACKUPS-${ymdlb}`, // Lower bound timestamp  
  `${pubkey}-GET-BACKUPS-${ymdub}`, // Upper bound timestamp  
];  
```

* **Signature Verification**:

  * The server uses the user’s **SLH-DSA public key** to verify the signature against all possible messages.
  * Ensures the request is recent and untampered.

  ```tsx
  const valid = slh.slh_dsa_shake_256f.verify(  
    pubkeyBytes,  
    messageBuffer,  
    signature  
  );  
  ```

#### **Check 2: Ownership Proof**

* Ownership is verified through SLH-DSA signature. Since ML-KEM and SLH-DSA keys are derived from the same mnemonic, validating SLH-DSA signatures proves control over the ML-KEM private key.

```typescript
// Verify SLH-DSA signature to prove ownership of ML-KEM key
let provenOwnership = false;
for (const message of legitMessages) {
  const valid = slh.slh_dsa_shake_256f.verify(
    pubkeyBytes, // SLH-DSA public key (derived from same mnemonic as ML-KEM key)
    Buffer.from(message, "utf8"),
    byteStringToBytes(signature)
  );
  if (valid) {
    provenOwnership = true;
    break;
  }
}
if (!provenOwnership) {
  throw new HttpError(HttpStatus.BadRequest, ERROR_MESSAGE.INVALID_SIGNATURE);
}
```

<mark style="color:red;">**Backup Retrieval & Decryption**</mark>

#### **Step 1: Fetching the Backup**

* Users request backups via their public key and a timestamped signature.

  ```tsx
  const backup = await getBackup(userId);
  ```

#### **Step 2: ML-KEM Decryption**

* **Key Decapsulation**:

  * The user’s **ML-KEM private key** decrypts the ciphertext to recover the shared secret.

  ```tsx
  const sharedSecret = ml_kem.decapsulate(ciphertext, privateKey);
  ```
* **Symmetric Decryption**:
  * The shared secret decrypts the symmetrically encrypted data.

#### **Step 3: Data Reconstruction**

* The decrypted **`Buffer`** is parsed back into JSON.
* Accounts are reinitialized in the wallet.

  ```tsx
  const decryptedBackup: BackupData = JSON.parse(decryptedData.toString());
  ```


---

# Agent Instructions: 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.qsafewallet.com/technical-details/ml-kem-encryption-for-backups.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.
