> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cyborg.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Managing Encryption Keys

Encryption keys are one of the most critical elements that enable the security guarantees of CyborgDB. By default, one key is used for the entire index, and it is used to generate and secure other encryption keys, including:

* Encrypted index tokens
* Index centroid salted hashes
* Index payload (embedding) encryption
* Item content encryptions
* Encrypted query tokens

This main key, known in the code as the `index_key`, is a 256-bit symmetric cryptographic key—the same you would find when using AES-256 encryption. CyborgDB's cryptography is based entirely on well-established cryptographic standards, including AES, HMAC, and SHA-3 (Keccak).

Without the correct `index_key`, it is impossible to use a CyborgDB Encrypted Index. You cannot upsert vectors, query the index, or even delete it. Hence, it is critical to manage these encryption keys safely.

***

## Generating Key Locally (for Development)

<Warning>**Do not store keys locally for production purposes.** For production environments, always use secure options such as Hardware Security Modules (HSMs) or a Key Management Service (KMS). See [Using Key Management Services (for Production)](#using-key-management-services-for-production).</Warning>

For local development and evaluation, you can generate a 256-bit encryption key locally and use it in your calls to CyborgDB. Here’s how you can do this using OpenSSL and integrate it with CyborgDB in Python.

<Steps>
  <Step title="Generate a Key with OpenSSL">
    Run the following command to generate a 256-bit encryption key, encoded in Base64:

    ```bash theme={null}
    openssl rand -base64 32 > index_key.txt
    ```

    This saves the key to a file named `index_key.txt`. Ensure that this file is kept secure and not included in your source control.
  </Step>

  <Step title="Use the Key in Python">
    You can either load the key directly from the file and use it with CyborgDB service SDKs.

    <CodeGroup>
      ```python Python SDK icon="python" theme={null}
      from cyborgdb import Client
      import base64

      # Create a client
      client = Client(
          base_url='http://localhost:8000', 
          api_key='your-api-key'
      )

      # Load the encryption key
      with open("index_key.txt", "r") as key_file:
          key_b64 = key_file.read().strip()
          index_key = base64.b64decode(key_b64)

      # Use the encryption key
      index = client.create_index("index_name", index_key)
      ```

      ```javascript JavaScript SDK icon="js" theme={null}
      import { Client } from 'cyborgdb';
      import fs from 'fs';

      // Create a client
      const client = new Client({ 
          baseUrl: 'http://localhost:8000', 
          apiKey: 'your-api-key' 
      });

      // Load the encryption key
      const keyB64 = fs.readFileSync("index_key.txt", 'utf8').trim();
      const indexKey = new Uint8Array(Buffer.from(keyB64, 'base64'));
      const indexName = "indexName";

      // Use the encryption key
      const index = await client.createIndex({ indexName, indexKey });
      ```

      ```typescript TypeScript SDK icon="code" theme={null}
      import { Client } from 'cyborgdb';
      import fs from 'fs';

      // Create a client
      const client = new Client({ 
          baseUrl: 'http://localhost:8000', 
          apiKey: 'your-api-key' 
      });

      // Load the encryption key
      const keyB64 = fs.readFileSync("index_key.txt", 'utf8').trim();
      const indexKey = new Uint8Array(Buffer.from(keyB64, 'base64'));
      const indexName = "indexName";

      // Use the encryption key
      const index = await client.createIndex({ indexName, indexKey });
      ```

      ```go Go SDK icon="golang" theme={null}
      package main

      import (
          "context"
          "encoding/base64"
          "io/ioutil"
          "log"

          "github.com/cyborginc/cyborgdb-go"
      )

      func main() {
          // Create a client
          client, err := cyborgdb.NewClient("http://localhost:8000", "your-api-key")
          if err != nil {
              log.Fatal(err)
          }

          // Load the encryption key
          keyB64, err := ioutil.ReadFile("index_key.txt")
          if err != nil {
              log.Fatal(err)
          }

          indexKey, err := base64.StdEncoding.DecodeString(string(keyB64))
          if err != nil {
              log.Fatal(err)
          }

          // Use the encryption key
          index, err := client.CreateIndex(context.Background(), &cyborgdb.CreateIndexParams{
              IndexName: "index_name",
              IndexKey:  indexKey,
          })
          if err != nil {
              log.Fatal(err)
          }

          log.Printf("Created index: %s", index.GetIndexName())
      }
      ```

      ```bash cURL icon="rectangle-terminal" theme={null}
      # Load the base64 key from file and use in REST API
      KEY_B64=$(cat index_key.txt)

      # Convert base64 to hex format for REST API
      # Note: REST API expects 64-character hex string
      curl -X POST "http://localhost:8000/v1/indexes/create" \
           -H "X-API-Key: your-api-key" \
           -H "Content-Type: application/json" \
           -d "{
             \"index_name\": \"test_index\",
             \"index_key\": \"$(echo $KEY_B64 | base64 -d | xxd -p -c 32)\"
           }"
      ```
    </CodeGroup>
  </Step>
</Steps>

Again, this should only be used for development and evaluation purposes; do not store encryption keys locally for production use.

***

## Using Key Management Services (for Production)

For production environments, a Key Management Service (KMS) or Hardware Security Module (HSM) is strongly recommended to securely store and manage encryption keys. This ensures the highest level of security by isolating the keys from application logic and providing robust access controls.

### Overview of KMS

A KMS is a managed service that provides centralized control over encryption keys, including:

* **Key Generation:** Automatically generating keys with required levels of entropy.
* **Secure Storage:** Storing keys in a tamper-proof environment.
* **Access Control:** Enforcing strict role-based access control (RBAC) policies.
* **Auditing:** Logging key usage for compliance and monitoring.

### Supported KMS Providers

CyborgDB can integrate with popular KMS providers, such as:

* **AWS Key Management Service (AWS KMS)**
* **Google Cloud Key Management (Google Cloud KMS)**
* **Azure Key Vault**
* **HashiCorp Vault**

***

## Step-by-Step Example: AWS KMS

<Steps>
  <Step title="Generate a Data Key Using AWS KMS">
    **Option A: Command Line**

    Use the AWS CLI to generate a data key:

    ```bash theme={null}
    aws kms generate-data-key \
        --key-id <Your-Key-Id> \
        --key-spec AES_256 \
        --output json
    ```

    * Replace `<Your-Key-Id>` with your KMS Key ID or ARN.
    * The command outputs a JSON object containing both the plaintext key and the encrypted key.

    **Example Output:**

    ```json theme={null}
    {
    "CiphertextBlob": "<Base64-encoded encrypted key>",
    "Plaintext": "<Base64-encoded plaintext key>",
    "KeyId": "arn:aws:kms:region:account-id:key/Your-Key-Id"
    }
    ```

    **Note:** The `Plaintext` and `CiphertextBlob` are Base64-encoded binary data.

    **Option B: Python**

    ```python theme={null}
    import boto3

    # Initialize AWS KMS client
    kms_client = boto3.client('kms')

    # Generate a data key
    response = kms_client.generate_data_key(
        KeyId='Your-Key-Id',  # Replace with your KMS Key ID or ARN
        KeySpec='AES_256'
    )

    # Extract the plaintext and encrypted data key
    plaintext_key = response['Plaintext']       # This is the raw binary key
    encrypted_key = response['CiphertextBlob']  # This is the encrypted key
    ```
  </Step>

  <Step title="Store the Encrypted Key">
    * **Encrypted Key:** Since it's encrypted, you can safely store it in your application's configuration file, environment variable, or secure parameter store.

    Example of storing the encrypted key in Base64-encoded format:

    ```python theme={null}
    import base64

    # Base64-encode the encrypted key for storage
    encrypted_key_b64 = base64.b64encode(encrypted_key).decode('utf-8')

    # Store 'encrypted_key_b64' in your application's configuration
    ```
  </Step>

  <Step title="Use the Encrypted Key in Your Application at Runtime">
    In your application code, decrypt the encrypted key at runtime using AWS KMS:

    <CodeGroup>
      ```python Python SDK icon="python" theme={null}
      import boto3
      import base64
      from cyborgdb import Client

      # Create a client
      client = Client(
          base_url='http://localhost:8000',
          api_key='your-api-key'
      )

      # Initialize AWS KMS client
      kms_client = boto3.client('kms')

      # Load the encrypted key from your configuration
      encrypted_key_b64 = '...'  # Replace with your stored encrypted key (Base64-encoded)

      # Decode the Base64-encoded encrypted key
      encrypted_key = base64.b64decode(encrypted_key_b64)

      # Decrypt the key at runtime
      response = kms_client.decrypt(
          CiphertextBlob=encrypted_key
      )
      index_key = response['Plaintext']  # This is your 256-bit key

      # Use the key with CyborgDB
      index = client.create_index("my_index", index_key)
      ```

      ```javascript JavaScript SDK icon="js" theme={null}
      import { Client } from 'cyborgdb';
      const AWS = require('aws-sdk');

      // Create a client
      const client = new Client({ 
          baseUrl: 'http://localhost:8000', 
          apiKey: 'your-api-key' 
      });

      // Initialize AWS KMS client
      const kms = new AWS.KMS();

      // Load the encrypted key from your configuration
      const encryptedKeyB64 = '...';  // Replace with your stored encrypted key (Base64-encoded)

      // Decode the Base64-encoded encrypted key
      const encryptedKey = Buffer.from(encryptedKeyB64, 'base64');

      // Decrypt the key at runtime
      const response = await kms.decrypt({
          CiphertextBlob: encryptedKey
      }).promise();
      const indexKey = new Uint8Array(response.Plaintext);  // This is your 256-bit key

      // Use the key with CyborgDB
      const index = await client.createIndex({ indexName: "my_index", indexKey, indexConfig });
      ```

      ```typescript TypeScript SDK icon="code" theme={null}
      import { Client } from 'cyborgdb';
      const AWS = require('aws-sdk');

      // Create a client
      const client = new Client({ 
          baseUrl: 'http://localhost:8000', 
          apiKey: 'your-api-key' 
      });

      // Initialize AWS KMS client
      const kms = new AWS.KMS();

      // Load the encrypted key from your configuration
      const encryptedKeyB64 = '...';  // Replace with your stored encrypted key (Base64-encoded)

      // Decode the Base64-encoded encrypted key
      const encryptedKey = Buffer.from(encryptedKeyB64, 'base64');

      // Decrypt the key at runtime
      const response = await kms.decrypt({
          CiphertextBlob: encryptedKey
      }).promise();
      const indexKey = new Uint8Array(response.Plaintext);  // This is your 256-bit key

      // Use the key with CyborgDB
      const index = await client.createIndex({ indexName: "my_index", indexKey, indexConfig });
      ```

      ```go Go SDK icon="golang" theme={null}
      package main

      import (
          "context"
          "encoding/base64"
          "log"

          "github.com/aws/aws-sdk-go/aws/session"
          "github.com/aws/aws-sdk-go/service/kms"
          "github.com/cyborginc/cyborgdb-go"
      )

      func main() {
          // Create a client
          client, err := cyborgdb.NewClient("http://localhost:8000", "your-api-key")
          if err != nil {
              log.Fatal(err)
          }

          // Initialize AWS KMS client
          sess, err := session.NewSession()
          if err != nil {
              log.Fatal(err)
          }
          kmsClient := kms.New(sess)

          // Load the encrypted key from your configuration
          encryptedKeyB64 := "..." // Replace with your stored encrypted key (Base64-encoded)

          // Decode the Base64-encoded encrypted key
          encryptedKey, err := base64.StdEncoding.DecodeString(encryptedKeyB64)
          if err != nil {
              log.Fatal(err)
          }

          // Decrypt the key at runtime
          decryptOutput, err := kmsClient.Decrypt(&kms.DecryptInput{
              CiphertextBlob: encryptedKey,
          })
          if err != nil {
              log.Fatal(err)
          }
          indexKey := decryptOutput.Plaintext // This is your 256-bit key

          // Use the key with CyborgDB
          index, err := client.CreateIndex(context.Background(), &cyborgdb.CreateIndexParams{
              IndexName: "my_index",
              IndexKey:  indexKey,
          })
          if err != nil {
              log.Fatal(err)
          }

          log.Printf("Created index: %s", index.GetIndexName())
      }
      ```

      ```bash cURL icon="rectangle-terminal" theme={null}
      # Decrypt key using AWS CLI and use with REST API
      ENCRYPTED_KEY_B64="your_encrypted_key_here"

      # Decrypt the key using AWS KMS
      DECRYPTED_KEY=$(aws kms decrypt \
          --ciphertext-blob "$(echo $ENCRYPTED_KEY_B64 | base64 -d | base64)" \
          --output text --query Plaintext | base64 -d | xxd -p -c 32)

      # Use the decrypted key with CyborgDB REST API
      curl -X POST "http://localhost:8000/v1/indexes/create" \
           -H "X-API-Key: your-api-key" \
           -H "Content-Type: application/json" \
           -d "{
             \"index_name\": \"my_index\",
             \"index_key\": \"$DECRYPTED_KEY\"
           }"
      ```
    </CodeGroup>

    **Explanation:**

    * **Encrypted Key Storage:** The encrypted key (`encrypted_key_b64`) is safe to store in configuration files since it's encrypted.
    * **Runtime Decryption:** The `kms_client.decrypt` method securely retrieves the plaintext key at runtime.
  </Step>

  <Step title="Ensure IAM Permissions">
    Your application needs permission to use the `kms:Decrypt` action. Attach a policy to your IAM role or user:

    ```json theme={null}
    {
    "Version": "2012-10-17",
    "Statement": [
        {
        "Effect": "Allow",
        "Action": "kms:Decrypt",
        "Resource": "arn:aws:kms:your-region:your-account-id:key/Your-Key-Id"
        }
    ]
    }
    ```
  </Step>
</Steps>

### Benefits of This Approach

* **Security:** The plaintext key is never stored persistently. It's only available in memory during runtime.
* **Simplicity:** You can generate and manage the key using AWS KMS and standard AWS tools.
* **No Need for Secure Storage:** Since the encrypted key is safe to store in your application's configuration, you don't need additional secure storage solutions.

By generating the data key using AWS KMS and storing only the encrypted key, you can securely manage your encryption key without needing to store it securely elsewhere. Your application decrypts the encrypted key at runtime using AWS KMS, ensuring that the plaintext key is only available in memory during execution.
