Skip to main content
CyborgDB supports role-based access control (RBAC) through per-user keys. The holder of the root index KEK can mint per-user wrapped keys that grant read and/or write access to an index.

How RBAC works

  • Per-index KEK. Each index is encrypted under a 32-byte Key-Encryption-Key (KEK), the index_key. CyborgDB wraps a data key (DEK) under the KEK internally — callers only ever handle the KEK.
  • Per-user keys. The root KEK holder calls CreateUserKeys to wrap the index key under a per-user 32-byte key (user_kek), granting read and/or write access. The set of wraps that exist defines the permission set — there is no separate permission flag. A read-only user simply has no write wrap.
  • Root-gated administration. Creating, deleting, and listing user keys always requires the root index KEK.
  • User load. A user then opens the index with their own user_kek, scoped to their user_id:
    auto index = client.LoadIndex(index_name, user_kek, /*logger=*/nullptr, user_id);
    
    Per-operation, the gate is enforced — a read-only user’s Upsert/Delete are rejected.
Pass a per-user key context to data operations as cyborg::KeyContext{user_kek, user_id} where user_id is a std::array<uint8_t, 16> and user_kek is a std::array<uint8_t, 32>.

CreateUserKeys

void CreateUserKeys(const std::array<uint8_t, 16>& user_id,
                    const std::array<uint8_t, 32>& index_key,
                    const std::array<uint8_t, 32>& user_kek,
                    bool grant_read,
                    bool grant_write);
Mints per-user wrapped keys granting the requested permissions.

Parameters

ParameterTypeDescription
user_idstd::array<uint8_t, 16>16-byte user identifier.
index_keystd::array<uint8_t, 32>The root index KEK (admin gate).
user_kekstd::array<uint8_t, 32>The user’s 32-byte key under which access is wrapped.
grant_readboolGrant read access.
grant_writeboolGrant write access.
At least one of grant_read / grant_write must be true.

Exceptions

  • Throws if the supplied key is not the root index KEK.
  • Throws if the user keys could not be created.

DeleteUserKeys

void DeleteUserKeys(const std::array<uint8_t, 16>& user_id,
                    const std::array<uint8_t, 32>& index_key);
Revokes a user’s access by deleting their wrapped keys. Idempotent and root-gated.

Parameters

ParameterTypeDescription
user_idstd::array<uint8_t, 16>16-byte user identifier to revoke.
index_keystd::array<uint8_t, 32>The root index KEK (admin gate).

Exceptions

  • Throws if the supplied key is not the root index KEK.

ListUserKeys

std::vector<UserKeyInfo> ListUserKeys(const std::array<uint8_t, 32>& index_key);
Lists all users that have keys for the index and their permissions. Root-gated.

Parameters

ParameterTypeDescription
index_keystd::array<uint8_t, 32>The root index KEK (admin gate).

Returns

std::vector<UserKeyInfo>: One entry per user. The UserKeyInfo struct:
struct UserKeyInfo {
    std::array<uint8_t, 16> user_id;
    bool has_read;
    bool has_write;
};

Exceptions

  • Throws if the supplied key is not the root index KEK.

Example Usage

#include "cyborgdb_core/client.hpp"
#include "cyborgdb_core/encrypted_index.hpp"
#include <openssl/rand.h>
#include <array>

// ... Initialize the client and load/create the index with the root index_key ...

// 16-byte user identifier and the user's 32-byte key (16/32 random bytes each)
std::array<uint8_t, 16> user_id;
std::array<uint8_t, 32> user_kek;
RAND_bytes(user_id.data(), user_id.size());
RAND_bytes(user_kek.data(), user_kek.size());

// Admin (root KEK holder) grants the user read-only access
index->CreateUserKeys(user_id, index_key, user_kek, /*grant_read=*/true, /*grant_write=*/false);

// Inspect current users
for (const auto& info : index->ListUserKeys(index_key)) {
    std::cout << "read=" << info.has_read << " write=" << info.has_write << "\n";
}

// The user loads the index scoped to their identity
auto user_index = client.LoadIndex("my_index", user_kek, /*logger=*/nullptr, user_id);

// Per-operation, the user passes a per-user key context
cyborg::Array2D<float> q{{0.1f, 0.2f, 0.3f, 0.4f}};
auto results = user_index->Query(q, cyborg::QueryParams{}, cyborg::KeyContext{user_kek, user_id});

// Revoke access when done
index->DeleteUserKeys(user_id, index_key);