Skip to content

数据加密

OpenViking 提供透明的静态数据加密,确保多租户环境下的数据安全与隔离。

概述

为什么需要加密

在多租户架构中,不同客户(账户)的资源文件、记忆和技能都存储在共享的 AGFS 实例中。加密确保:

  • 即使攻击者获得 AGFS 磁盘访问权限,也无法读取任何客户的明文数据
  • 不同账户的数据使用独立密钥加密,实现租户隔离
  • 所有加密解密操作集中在 VikingFS 层,AGFS 和外部对象存储只看到密文

对谁透明

加密功能对用户和开发者完全透明:

  • 客户端 API 无变化:现有代码无需修改
  • 应用层无感知:读写操作与未加密时完全相同
  • 向后兼容:未加密的旧文件仍可正常读取

三层密钥架构

OpenViking 采用信封加密(Envelope Encryption)架构,使用三层密钥体系:

┌─────────────────────────────────────────────────────────┐
│  Layer 1: Root Key(根密钥)                          │
│  • 整个 OpenViking 实例全局唯一                       │
│  • 存储:KMS 服务 / ~/.openviking/master.key         │
│  • 用途:派生所有账户密钥                              │
└────────────────────┬────────────────────────────────────┘
                     │ HKDF 派生

┌─────────────────────────────────────────────────────────┐
│  Layer 2: Account Key(账户密钥,KEK)                │
│  • 每个账户一个独立密钥                                │
│  • 不存储,运行时派生                                  │
│  • 用途:加密该账户下的所有文件密钥                    │
└────────────────────┬────────────────────────────────────┘
                     │ AES-256-GCM 加密

┌─────────────────────────────────────────────────────────┐
│  Layer 3: File Key(文件密钥,DEK)                   │
│  • 每次写操作生成新的随机密钥                          │
│  • 加密后存储在文件头(信封)中                        │
│  • 用途:加密实际文件内容                              │
└─────────────────────────────────────────────────────────┘

密钥层次说明

层级名称说明数量
Root Key根密钥整个系统的主密钥,用于派生所有账户密钥1 个实例
Account Key账户密钥每个账户独立的密钥,从根密钥派生每个账户 1 个
File Key文件密钥每个文件的一次性随机密钥每次写入 1 个

密钥提供程序

OpenViking 支持三种密钥提供程序,适应不同的部署场景:

提供程序适用场景Root Key 存储特点
Local开发环境、单节点部署本地文件 ~/.openviking/master.key简单,无需外部服务
Vault生产环境、多云部署HashiCorp Vault Transit Engine企业级密钥管理,支持密钥版本控制
Volcengine KMS火山引擎云部署火山引擎 KMS云原生密钥管理服务

Local(本地文件)

适合开发环境和单节点部署:

json
{
  "encryption": {
    "enabled": true,
    "provider": "local",
    "local": {
      "key_file": "~/.openviking/master.key"
    }
  }
}

初始化命令

bash
ov crypto init-key --output ~/.openviking/master.key

Vault(HashiCorp Vault)

适合生产环境和多云部署:

json
{
  "encryption": {
    "enabled": true,
    "provider": "vault",
    "vault": {
      "address": "https://vault.example.com:8200",
      "token": "hvs.your-vault-token",
      "mount_point": "transit",
      "kv_mount_point": "secret",
      "kv_version": 1,
      "root_key_name": "openviking-root-key",
      "encrypted_root_key_key": "openviking-encrypted-root-key"
    }
  }
}

Volcengine KMS(火山引擎)

适合火山引擎云部署:

json
{
  "encryption": {
    "enabled": true,
    "provider": "volcengine_kms",
    "volcengine_kms": {
      "key_id": "d926aa0d-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
      "region": "cn-beijing",
      "access_key": "AKLTxxxxxxxxxxxxxxxxxx",
      "secret_key": "Tmpxxxxxxxxxxxxxxxxxxxxxx",
      "endpoint": null,
      "key_file": "~/.openviking/openviking-volcengine-root-key.enc"
    }
  }
}

工作原理

写流程

客户端              VikingFS             FileEncryptor        KeyManager        AGFS
  │                   │                       │                    │             │
  │  write(uri, data) │                       │                    │             │
  │──────────────────>│                       │                    │             │
  │                   │  encrypt(account_id,  │                    │             │
  │                   │           plaintext)  │                    │             │
  │                   │──────────────────────>│                    │             │
  │                   │                       │derive_account_key()│             │
  │                   │                       │───────────────────>│             │
  │                   │                       │<───────────────────│             │
  │                   │                       │  account_key       │             │
  │                   │  1. 生成随机 File Key                        │             │
  │                   │  2. 用 File Key 加密内容                     │             │
  │                   │  3. 用 Account Key 加密 File Key            │             │
  │                   │  4. 构建信封格式                             │             │
  │                   │<──────────────────────│                    │             │
  │                   │  ciphertext           │                    │             │
  │                   │─────────────────────────────────────────────────────────>│
  │                   │                       │                    │  Write      │
  │<──────────────────│                       │                    │             │
  │   success         │                       │                    │             │

读流程

客户端              VikingFS             FileEncryptor          KeyManager        AGFS
  │                   │                       │                     │             │
  │  read(uri)        │                       │                     │             │
  │──────────────────>│                       │                     │             │
  │                   │──────────────────────────────────────────────────────────>│
  │                   │                       │                     │  Read       │
  │                   │<──────────────────────────────────────────────────────────│
  │                   │  raw_bytes            │                     │             │
  │                   │  检查魔术数 == "OVE1"?  │                     │             │
  │                   │  是 → decrypt()       │                      │             │
  │                   │──────────────────────>│                     │             │
  │                   │                       │ derive_account_key()│             │
  │                   │                       │────────────────────>│             │
  │                   │                       │<────────────────────│             │
  │                   │                       │  account_key        │             │
  │                   │  1. 解析信封格式                              │             │
  │                   │  2. 用 Account Key 解密 File Key             │             │
  │                   │  3. 用 File Key 解密内容                      │             │
  │                   │<──────────────────────│                     │             │
  │                   │  plaintext            │                     │             │
  │<──────────────────│                       │                     │             │
  │   content         │                       │                     │             │

信封格式

加密文件使用统一的信封格式,以魔术数 OVE1(OpenViking Encryption v1)开头:

┌─────────────────────────────────────────────────────────────┐
│  魔术数   │  版本    │  Provider   │  加密的 File Key  │  ..   │
│  4 字节   │  1 字节  │   1 字节    │     可变长度       │  ...  │
│  "OVE1"  │   0x01  │  0x01=local │                  │  ...  │
└─────────────────────────────────────────────────────────────┘
  • 如果文件不以 OVE1 开头,视为未加密文件,直接返回明文
  • 支持向后兼容,旧文件无需迁移

多租户隔离

不同账户的数据使用独立的 Account Key 加密:

  • 账户 A 的密钥无法解密账户 B 的文件
  • 即使 AGFS 被完全访问,没有对应密钥也无法读取数据
  • 租户隔离在密钥层面实现,不依赖存储层权限

配置示例

详细配置说明请参考 配置文档

相关文档

Released under the Apache-2.0 License.