https://github.com/langgenius/dify查看设置的apikey

现在我已经掌握了足够的信息,来做一个完整清晰的分析。好的,现在我来给出一个完整的分析。

Dify provider_model_credentials.encrypted_config 解密分析

整体加密架构

Dify 使用 PKCS1_OAEP 加密来保护 API key。每个用户(tenant)都有一个唯一的密钥对,确保 API key 的机密性。

实际上从源码看,Dify 用的是混合加密(RSA + AES),下面是完整的加解密流程图:### 核心源码解读

加密逻辑api/libs/rsa.py):

python 复制代码
prefix_hybrid = b"HYBRID:"

def encrypt(text: str, public_key: ...) -> bytes:
    aes_key = get_random_bytes(16)             # 随机生成 AES-128 Key
    cipher_aes = AES.new(aes_key, AES.MODE_EAX)
    ciphertext, tag = cipher_aes.encrypt_and_digest(text.encode())  # AES 加密明文

    cipher_rsa = gmpy2_pkcs10aep_cipher.new(rsa_key)
    enc_aes_key = cipher_rsa.encrypt(aes_key)  # RSA-OAEP 加密 AES Key

    # 拼接成最终密文
    return prefix_hybrid + enc_aes_key + cipher_aes.nonce + tag + ciphertext

所以 encrypted_config 字段的字节结构为:

复制代码
HYBRID: | enc_aes_key(256B) | nonce(16B) | tag(16B) | ciphertext(变长)

解密逻辑api/core/provider_manager.py):

解密时,系统通过 encrypter.get_decrypt_decoding(tenant_id) 获取租户的 RSA 私钥,再调用 encrypter.decrypt_token_with_decodingprovider_model_credentials 中各字段的加密值进行解密。

如何手动查看 API Key

你需要同时具备两个东西:

1. 从数据库取出密文

sql 复制代码
-- 找到目标记录
SELECT id, tenant_id, model_name, encrypted_config
FROM provider_model_credentials
WHERE provider_name = 'openai';

2. 取出对应租户的 RSA 私钥

私钥存储位置取决于你的文件存储配置(STORAGE_TYPE),路径为 privkeys/{tenant_id}/private.pem

  • 本地部署:默认在 api/storage/privkeys/{tenant_id}/private.pem
  • S3/OSS 等:在对应的 Bucket 中

3. 用 Python 脚本解密

python 复制代码
from Crypto.PublicKey import RSA
from Crypto.Cipher import AES
import base64

prefix = b"HYBRID:"

def decrypt_api_key(encrypted_hex_or_bytes: bytes, private_key_pem: bytes) -> str:
    # 1. 去掉前缀
    data = encrypted_hex_or_bytes
    if data.startswith(prefix):
        data = data[len(prefix):]

    # 2. 加载私钥
    rsa_key = RSA.import_key(private_key_pem)
    key_size = rsa_key.size_in_bytes()  # 256 bytes for RSA-2048

    # 3. 拆分各部分
    enc_aes_key = data[:key_size]
    nonce       = data[key_size:key_size+16]
    tag         = data[key_size+16:key_size+32]
    ciphertext  = data[key_size+32:]

    # 4. RSA-OAEP 解密 AES Key
    from libs import gmpy2_pkcs10aep_cipher  # Dify 的 OAEP 实现
    cipher_rsa = gmpy2_pkcs10aep_cipher.new(rsa_key)
    aes_key = cipher_rsa.decrypt(enc_aes_key)

    # 5. AES-EAX 解密明文
    cipher_aes = AES.new(aes_key, AES.MODE_EAX, nonce=nonce)
    plaintext = cipher_aes.decrypt_and_verify(ciphertext, tag)
    return plaintext.decode()

# 使用
with open("private.pem", "rb") as f:
    pem = f.read()

# encrypted_config 字段值(bytes)
api_key = decrypt_api_key(encrypted_config_bytes, pem)
print(api_key)

注意事项

关键点 说明
每个 tenant 独立密钥 私钥按 tenant_id 分目录存放,不同租户不能互解
encrypted_config 的格式 provider_model_credentials 表里存的是 JSON 序列化后的字段级加密(每个敏感字段单独加密),不是整条记录加密
SECRET_KEY 环境变量 用于 AES-256 加密第三方 OAuth 凭证,与 model credentials 是不同的加密路径
不要直接改密钥 替换 RSA 私钥后,已存储的所有 encrypted_config 都将无法解密

简单来说:encrypted_config 是 RSA+AES 混合加密的密文,解密必须持有对应 tenant_id 的 RSA 私钥文件,这个文件在你的文件存储后端(本地磁盘或对象存储)中,而不在数据库里。

相关推荐
doiito17 小时前
【Agent Harness】Gliding Horse 给 Agent OS 装上双曲空间引擎与默克尔树边云同步
ai·rust·架构设计·系统设计·ai agent
knqiufan20 小时前
从 Python 到 TypeScript,用 GLM-5.2 跑通 PowerMem SDK 的长程任务工程
ai·memory·agentic·powermem
小白跃升坊2 天前
Codex 增强部署:基于 Codex++ 接入 DeepSeek
ai·ai编程·codex·deepseek·ai coding·codex++
AlfredZhao2 天前
GPT 省钱,不是别用最新模型,而是别浪费缓存
gpt·ai
doiito2 天前
【Agent Harness】Gliding Horse 本体论系统设计:给 AI Agent 装上“语义大脑”
ai·rust·架构设计·系统设计·ai agent
小七-七牛开发者2 天前
周一上线 | SpaceX 收购 Cursor、支付宝进入 AI 时代、DeepSeek 完成 500 亿元融资
ai·agent·token·glm·智谱·claudecode·ai coding·周一上线
doiito3 天前
【Agent Harness】为什么我把 JSON‑LD “编译成 DAG” 后,整个 Agent 平台立刻聪明了
ai·rust·架构设计·系统设计·ai agent
xiezhr3 天前
折腾半小时,终于让AI 能直接帮我写飞书文档了
ai·飞书·ai agent·飞书cli·飞书文档
岳小哥AI3 天前
Claude Fable和Claude Mythos 5同时发布:注意力机制下愈加强大的AI大模型
ai·ai基础
Artech3 天前
[MAF预定义的AIContextProvider-04]Mem0Provider——长期记忆基于的云端解决方案
ai·agent·maf·aicontextprovider·chathistorymemoryprovider·mem0provider