第2章:多租户密钥体系设计
🎯 本章目标
学完这一章,你将理解:
– 每个客户是否需要独立的公私钥对
– 三种密钥体系方案的设计
– 如何根据业务场景选择方案
预计学习时间: 40分钟
2.1 业务场景分析
你的业务场景
你是平台方(SaaS提供商)
├── 客户A(某医院)
│ ├── 北京数据中心
│ ├── 上海数据中心
│ └── 100台设备
│
├── 客户B(某工厂)
│ ├── 深圳工厂
│ └── 50台设备
│
└── 客户C(某学校)
├── 主校区
├── 分校区
└── 30台设备
核心问题
问题1:每个客户是否需要独立的公私钥对?
– 如果是,如何管理这么多密钥?
– 如果不是,如何区分不同客户?
问题2:统一安装包如何处理密钥?
– 安装包内置什么密钥?
– 客户特定密钥如何注入?
问题3:客户导入设备时如何验证?
– 设备如何证明自己属于这个客户?
– 平台如何验证设备的合法性?
2.2 方案1:每客户一对密钥(简单方案)
设计思路
核心原则: 每个客户有独立的公私钥对
平台(你)
├── 平台根密钥对(Platform Root Key)
│ ├── 平台根公钥(公开)
│ └── 平台根私钥(绝对保密)
│
├── 客户A密钥对
│ ├── 客户A公钥
│ └── 客户A私钥
│
├── 客户B密钥对
│ ├── 客户B公钥
│ └── 客户B私钥
│
└── 客户C密钥对
├── 客户C公钥
└── 客户C私钥
密钥生成流程
class SimpleKeySystem:
"""
方案1:每客户一对密钥
"""
def __init__(self):
# 平台根密钥对(只生成一次)
self.platform_root_key = RSA.generate(4096)
self.platform_root_public = self.platform_root_key.publickey()
def create_customer(self, customer_id, customer_name):
"""
为新客户生成密钥对
"""
# 1. 生成客户专属密钥对
customer_key = RSA.generate(2048)
customer_public = customer_key.publickey()
# 2. 创建客户证书(用平台根私钥签名)
customer_cert = {
"customer_id": customer_id,
"customer_name": customer_name,
"public_key": customer_public.export_key().decode(),
"issued_at": datetime.now().isoformat(),
"valid_until": (datetime.now() + timedelta(days=365)).isoformat()
}
# 3. 用平台根私钥签名证书
cert_data = json.dumps(customer_cert, sort_keys=True)
hash_obj = SHA256.new(cert_data.encode())
signature = pkcs1_15.new(self.platform_root_key).sign(hash_obj)
customer_cert["signature"] = base64.b64encode(signature).decode()
# 4. 返回客户密钥包
return {
"customer_id": customer_id,
"private_key": customer_key.export_key().decode(),
"public_key": customer_public.export_key().decode(),
"certificate": customer_cert
}
信任链
[平台根证书](自签名)
↓ 签发
[客户A证书](包含客户A公钥)
↓ 签发
[设备1证书](包含设备1公钥)
验证流程:
1. 验证设备1证书 → 用客户A公钥验证
2. 验证客户A证书 → 用平台根公钥验证
3. 验证平台根证书 → 自签名(信任锚点)
设备导入流程
def import_device(self, customer_id, device_info):
"""
客户导入新设备
"""
# 1. 验证客户身份
customer = self.get_customer(customer_id)
if not customer:
raise Exception("客户不存在")
# 2. 为设备生成密钥对
device_key = RSA.generate(2048)
device_public = device_key.publickey()
# 3. 创建设备证书(用客户私钥签名)
device_cert = {
"device_id": device_info["id"],
"customer_id": customer_id,
"serial_number": device_info["serial"],
"public_key": device_public.export_key().decode(),
"issued_at": datetime.now().isoformat()
}
# 4. 用客户私钥签名
cert_data = json.dumps(device_cert, sort_keys=True)
hash_obj = SHA256.new(cert_data.encode())
customer_private_key = RSA.import_key(customer["private_key"])
signature = pkcs1_15.new(customer_private_key).sign(hash_obj)
device_cert["signature"] = base64.b64encode(signature).decode()
return {
"device_id": device_info["id"],
"private_key": device_key.export_key().decode(),
"certificate": device_cert
}
优缺点分析
优点:
– ✅ 简单直观,容易理解
– ✅ 客户隔离性好(每个客户独立密钥)
– ✅ 客户可以自己管理设备密钥
缺点:
– ❌ 密钥管理复杂(100个客户 = 100对密钥)
– ❌ 客户私钥需要安全分发(如何给客户?)
– ❌ 客户私钥泄露风险高(客户可能保管不善)
– ❌ 不支持多地域(一个客户只有一对密钥)
适用场景
✅ 适合:
- 客户数量少(<50个)
- 客户有专业IT团队
- 客户需要完全自主控制
❌ 不适合:
- 客户数量多(>100个)
- 客户IT能力弱
- 需要多地域部署
2.3 方案2:分层密钥体系(推荐方案)
设计思路
核心原则: 密钥分层管理,客户不持有私钥
平台密钥层级:
┌─────────────────────────────────┐
│ 平台根密钥(Platform Root) │
│ - 最高权限 │
│ - 离线保存在HSM │
└─────────────────────────────────┘
↓ 签发
┌─────────────────────────────────┐
│ 客户主密钥(Customer Master) │
│ - 每个客户一个 │
│ - 平台保管,客户不持有 │
└─────────────────────────────────┘
↓ 派生
┌─────────────────────────────────┐
│ 地域密钥(Region Key) │
│ - 每个数据中心一个 │
│ - 用于签发设备证书 │
└─────────────────────────────────┘
↓ 签发
┌─────────────────────────────────┐
│ 设备密钥(Device Key) │
│ - 每个设备一个 │
│ - 设备持有私钥 │
└─────────────────────────────────┘
完整代码实现
class HierarchicalKeySystem:
"""
方案2:分层密钥体系
"""
def __init__(self):
# 平台根密钥(4096位,最高安全级别)
self.platform_root_key = RSA.generate(4096)
self.platform_root_public = self.platform_root_key.publickey()
# 客户主密钥存储
self.customer_master_keys = {}
# 地域密钥存储
self.region_keys = {}
def create_customer(self, customer_id, customer_name):
"""
为客户创建主密钥
"""
# 1. 生成客户主密钥(平台保管)
customer_master_key = RSA.generate(2048)
# 2. 创建客户证书
customer_cert = {
"customer_id": customer_id,
"customer_name": customer_name,
"public_key": customer_master_key.publickey().export_key().decode(),
"issued_at": datetime.now().isoformat(),
"valid_until": (datetime.now() + timedelta(days=365)).isoformat(),
"key_usage": ["sign_device_cert", "derive_region_key"]
}
# 3. 用平台根私钥签名
cert_data = json.dumps(customer_cert, sort_keys=True)
hash_obj = SHA256.new(cert_data.encode())
signature = pkcs1_15.new(self.platform_root_key).sign(hash_obj)
customer_cert["signature"] = base64.b64encode(signature).decode()
# 4. 保存客户主密钥(平台保管,客户不持有)
self.customer_master_keys[customer_id] = {
"private_key": customer_master_key,
"public_key": customer_master_key.publickey(),
"certificate": customer_cert
}
return customer_cert
def create_region_key(self, customer_id, region_name):
"""
为客户的某个地域创建密钥
"""
# 1. 获取客户主密钥
customer_master = self.customer_master_keys.get(customer_id)
if not customer_master:
raise Exception("客户不存在")
# 2. 派生地域密钥(从客户主密钥派生)
region_key = RSA.generate(2048)
# 3. 创建地域证书
region_cert = {
"customer_id": customer_id,
"region_name": region_name,
"public_key": region_key.publickey().export_key().decode(),
"issued_at": datetime.now().isoformat(),
"valid_until": (datetime.now() + timedelta(days=365)).isoformat(),
"key_usage": ["sign_device_cert"]
}
# 4. 用客户主私钥签名
cert_data = json.dumps(region_cert, sort_keys=True)
hash_obj = SHA256.new(cert_data.encode())
signature = pkcs1_15.new(customer_master["private_key"]).sign(hash_obj)
region_cert["signature"] = base64.b64encode(signature).decode()
# 5. 保存地域密钥
region_id = f"{customer_id}:{region_name}"
self.region_keys[region_id] = {
"private_key": region_key,
"public_key": region_key.publickey(),
"certificate": region_cert
}
return region_cert
def import_device(self, customer_id, region_name, device_info):
"""
客户导入设备(在指定地域)
"""
# 1. 获取地域密钥
region_id = f"{customer_id}:{region_name}"
region_key = self.region_keys.get(region_id)
if not region_key:
raise Exception("地域不存在,请先创建地域密钥")
# 2. 为设备生成密钥对
device_key = RSA.generate(2048)
device_public = device_key.publickey()
# 3. 创建设备证书
device_cert = {
"device_id": device_info["id"],
"customer_id": customer_id,
"region_name": region_name,
"serial_number": device_info["serial"],
"public_key": device_public.export_key().decode(),
"issued_at": datetime.now().isoformat()
}
# 4. 用地域私钥签名
cert_data = json.dumps(device_cert, sort_keys=True)
hash_obj = SHA256.new(cert_data.encode())
signature = pkcs1_15.new(region_key["private_key"]).sign(hash_obj)
device_cert["signature"] = base64.b64encode(signature).decode()
return {
"device_id": device_info["id"],
"private_key": device_key.export_key().decode(),
"certificate": device_cert,
"certificate_chain": [
device_cert,
region_key["certificate"],
self.customer_master_keys[customer_id]["certificate"]
]
}
def verify_device(self, device_cert, cert_chain):
"""
验证设备证书链
"""
# 1. 验证设备证书(用地域公钥)
region_cert = cert_chain[1]
region_public_key = RSA.import_key(region_cert["public_key"])
cert_data = json.dumps({k: v for k, v in device_cert.items() if k != "signature"}, sort_keys=True)
hash_obj = SHA256.new(cert_data.encode())
signature = base64.b64decode(device_cert["signature"])
try:
pkcs1_15.new(region_public_key).verify(hash_obj, signature)
print("✅ 设备证书验证成功")
except:
print("❌ 设备证书验证失败")
return False
# 2. 验证地域证书(用客户主公钥)
customer_cert = cert_chain[2]
customer_public_key = RSA.import_key(customer_cert["public_key"])
cert_data = json.dumps({k: v for k, v in region_cert.items() if k != "signature"}, sort_keys=True)
hash_obj = SHA256.new(cert_data.encode())
signature = base64.b64decode(region_cert["signature"])
try:
pkcs1_15.new(customer_public_key).verify(hash_obj, signature)
print("✅ 地域证书验证成功")
except:
print("❌ 地域证书验证失败")
return False
# 3. 验证客户证书(用平台根公钥)
cert_data = json.dumps({k: v for k, v in customer_cert.items() if k != "signature"}, sort_keys=True)
hash_obj = SHA256.new(cert_data.encode())
signature = base64.b64decode(customer_cert["signature"])
try:
pkcs1_15.new(self.platform_root_public).verify(hash_obj, signature)
print("✅ 客户证书验证成功")
except:
print("❌ 客户证书验证失败")
return False
print("✅ 完整证书链验证成功")
return True
信任链示例
场景:客户A在北京数据中心导入设备001
证书链:
[平台根证书]
↓ 签发
[客户A主证书]
↓ 签发
[北京地域证书]
↓ 签发
[设备001证书]
验证流程:
1. 设备001连接平台
2. 设备001提供:设备证书 + 完整证书链
3. 平台验证:
- 设备证书 ← 用北京地域公钥验证
- 北京地域证书 ← 用客户A主公钥验证
- 客户A主证书 ← 用平台根公钥验证
4. 全部通过 → 设备合法 ✅
优缺点分析
优点:
– ✅ 支持多地域(每个地域独立密钥)
– ✅ 客户不持有私钥(降低泄露风险)
– ✅ 密钥管理集中(平台统一管理)
– ✅ 灵活性高(可以按地域撤销)
– ✅ 扩展性好(轻松支持新地域)
缺点:
– ❌ 实现复杂(需要管理多层密钥)
– ❌ 平台责任重(所有密钥都在平台)
– ❌ 需要HSM(硬件安全模块保护根密钥)
适用场景
✅ 适合:
- 客户数量多(>100个)
- 需要多地域部署
- 客户IT能力弱
- 需要集中管理
✅ 推荐场景:
- SaaS平台
- 多租户系统
- 跨国部署
2.4 方案3:混合密钥体系(最灵活)
设计思路
核心原则: 结合方案1和方案2的优点
平台层:
├── 平台根密钥(Platform Root)
│
客户层(两种模式):
├── 模式A:客户自管密钥(客户持有私钥)
│ └── 适合:大客户、有IT团队
│
└── 模式B:平台托管密钥(平台持有私钥)
└── 适合:小客户、无IT团队
代码实现
class HybridKeySystem:
"""
方案3:混合密钥体系
"""
def __init__(self):
self.platform_root_key = RSA.generate(4096)
self.customers = {}
def create_customer(self, customer_id, customer_name, key_mode="托管"):
"""
创建客户(支持两种模式)
key_mode: "自管" 或 "托管"
"""
customer_key = RSA.generate(2048)
customer_cert = {
"customer_id": customer_id,
"customer_name": customer_name,
"key_mode": key_mode,
"public_key": customer_key.publickey().export_key().decode(),
"issued_at": datetime.now().isoformat()
}
# 签名证书
cert_data = json.dumps(customer_cert, sort_keys=True)
hash_obj = SHA256.new(cert_data.encode())
signature = pkcs1_15.new(self.platform_root_key).sign(hash_obj)
customer_cert["signature"] = base64.b64encode(signature).decode()
if key_mode == "托管":
# 平台托管模式:平台保存私钥
self.customers[customer_id] = {
"mode": "托管",
"private_key": customer_key,
"public_key": customer_key.publickey(),
"certificate": customer_cert
}
return {
"customer_id": customer_id,
"mode": "托管",
"certificate": customer_cert,
"message": "密钥由平台托管,客户无需管理私钥"
}
else:
# 客户自管模式:客户保存私钥
self.customers[customer_id] = {
"mode": "自管",
"public_key": customer_key.publickey(),
"certificate": customer_cert
}
return {
"customer_id": customer_id,
"mode": "自管",
"private_key": customer_key.export_key().decode(),
"certificate": customer_cert,
"message": "请妥善保管私钥,平台不保存"
}
优缺点分析
优点:
– ✅ 最灵活(支持两种模式)
– ✅ 满足不同客户需求
– ✅ 可以平滑迁移(从托管到自管)
缺点:
– ❌ 最复杂(需要维护两套逻辑)
– ❌ 测试成本高
– ❌ 文档复杂
适用场景
✅ 适合:
- 客户类型多样(大客户+小客户)
- 需要灵活性
- 有足够的开发资源
2.5 三种方案对比
对比表
| 维度 | 方案1:每客户一对密钥 | 方案2:分层密钥体系 | 方案3:混合体系 |
|---|---|---|---|
| 复杂度 | ⭐ 简单 | ⭐⭐⭐ 复杂 | ⭐⭐⭐⭐ 很复杂 |
| 多地域支持 | ❌ 不支持 | ✅ 完美支持 | ✅ 支持 |
| 客户隔离 | ✅ 很好 | ✅ 很好 | ✅ 很好 |
| 密钥管理 | 客户自管 | 平台托管 | 两种模式 |
| 安全风险 | 客户私钥泄露 | 平台责任重 | 混合风险 |
| 扩展性 | ⭐⭐ 一般 | ⭐⭐⭐⭐⭐ 很好 | ⭐⭐⭐⭐ 好 |
| 适合客户数 | <50 | >100 | 任意 |
| 开发成本 | 低 | 中 | 高 |
| 维护成本 | 中 | 低 | 高 |
推荐选择
如果你的业务是:
├── 客户少(<50)且都有IT团队 → 方案1
├── 客户多(>100)或需要多地域 → 方案2 ⭐推荐
└── 客户类型多样,需要灵活性 → 方案3
2.6 本章小结
核心要点
- 方案1:每客户一对密钥,简单但不灵活
- 方案2:分层密钥体系,推荐用于多租户SaaS
- 方案3:混合体系,最灵活但最复杂
关键决策
每个客户是否需要独立密钥?
– ✅ 是的,每个客户都需要独立密钥
– 但密钥可以由平台托管(方案2)或客户自管(方案1)
推荐方案:方案2(分层密钥体系)
– 支持多地域
– 平台集中管理
– 客户无需管理私钥
– 扩展性好
🤔 思考题
-
场景题:如果客户A有3个数据中心(北京、上海、广州),使用方案2,需要生成几个密钥对?
-
安全题:方案1中,如果客户的私钥泄露了,会影响其他客户吗?
-
设计题:如果要支持客户从”平台托管”模式切换到”客户自管”模式,应该如何设计?
📚 下一章预告
第3章我们将学习多地域证书管理:
– 一个客户多个证书的详细设计
– 证书的层级关系
– 跨地域信任链的建立
继续加油!
本章关键词
– 多租户
– 密钥体系
– 分层密钥
– 证书链
– 信任链
– 客户隔离
– 地域密钥








最新评论
照片令人惊艳。万分感谢 温暖。
氛围绝佳。由衷感谢 感受。 你的博客让人一口气读完。敬意 真诚。
实用的 杂志! 越来越好!
又到年底了,真快!
研究你的文章, 我体会到美好的心情。
感谢激励。由衷感谢
好久没见过, 如此温暖又有信息量的博客。敬意。
很稀有, 这么鲜明的文字。谢谢。