implementing-api-key-security-controls
实施安全的API密钥生成、存储、轮换和吊销控制,防止API认证凭据泄露、暴力破解和滥用。 设计具有足够熵的API密钥格式,实施安全哈希存储,执行按密钥范围限制和速率限制, 监控公共仓库中的密钥泄露,并构建密钥轮换工作流。
Best use case
implementing-api-key-security-controls is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
实施安全的API密钥生成、存储、轮换和吊销控制,防止API认证凭据泄露、暴力破解和滥用。 设计具有足够熵的API密钥格式,实施安全哈希存储,执行按密钥范围限制和速率限制, 监控公共仓库中的密钥泄露,并构建密钥轮换工作流。
Teams using implementing-api-key-security-controls should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/implementing-api-key-security-controls/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How implementing-api-key-security-controls Compares
| Feature / Agent | implementing-api-key-security-controls | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
实施安全的API密钥生成、存储、轮换和吊销控制,防止API认证凭据泄露、暴力破解和滥用。 设计具有足够熵的API密钥格式,实施安全哈希存储,执行按密钥范围限制和速率限制, 监控公共仓库中的密钥泄露,并构建密钥轮换工作流。
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# 实施API密钥安全控制
## 适用场景
- 设计具有足够熵和可识别前缀的安全API密钥生成机制,用于泄露检测
- 实施服务端API密钥哈希存储(永不以明文存储密钥),使用SHA-256或bcrypt
- 构建支持零停机密钥替换的密钥轮换工作流
- 配置按密钥范围限制,将每个API密钥限制到特定端点、IP范围和速率限制
- 设置自动化监控,检测GitHub仓库、日志和客户端代码中的API密钥泄露
**不适用**将API密钥作为面向用户应用的唯一认证机制。API密钥最适合服务间通信和开发者访问。
## 前置条件
- 安全随机数生成器(os.urandom、secrets模块)用于密钥生成
- 具有静态加密功能的数据库用于存储哈希后的API密钥
- Redis或类似存储用于密钥到元数据的缓存和速率限制
- 密钥扫描工具(GitHub secret scanning、truffleHog、gitleaks)
- 用于密钥使用异常的监控和告警基础设施
## 工作流程
### 步骤1:安全API密钥生成
```python
import secrets
import hashlib
import hmac
import time
import json
from datetime import datetime, timedelta
class APIKeyManager:
"""管理安全API密钥生命周期:生成、存储、验证、轮换。"""
# 密钥格式:prefix_base64random(例如 sk_live_a1b2c3d4e5f6...)
# 前缀用于标识密钥类型和环境,便于泄露检测
KEY_PREFIXES = {
"live_secret": "sk_live_",
"test_secret": "sk_test_",
"live_public": "pk_live_",
"test_public": "pk_test_",
}
def __init__(self, db_connection, redis_connection):
self.db = db_connection
self.redis = redis_connection
def generate_key(self, key_type="live_secret", owner_id=None, scopes=None,
rate_limit=None, ip_allowlist=None, expires_days=365):
"""生成带元数据的新API密钥。"""
prefix = self.KEY_PREFIXES.get(key_type, "sk_live_")
# 生成32字节(256位)随机数
random_bytes = secrets.token_bytes(32)
key_body = secrets.token_urlsafe(32) # Base64url编码
# 客户端收到的完整API密钥(仅显示一次)
full_key = f"{prefix}{key_body}"
# 对密钥进行哈希处理用于存储(永不存储原始密钥)
key_hash = hashlib.sha256(full_key.encode()).hexdigest()
# 创建用于引用的短密钥ID(前8个字符)
key_id = f"{prefix}{key_body[:8]}..."
# 存储哈希密钥及元数据
key_metadata = {
"key_hash": key_hash,
"key_id": key_id,
"key_type": key_type,
"owner_id": owner_id,
"scopes": scopes or ["read"],
"rate_limit": rate_limit or {"requests": 1000, "window": 3600},
"ip_allowlist": ip_allowlist or [],
"created_at": datetime.utcnow().isoformat(),
"expires_at": (datetime.utcnow() + timedelta(days=expires_days)).isoformat(),
"last_used": None,
"is_active": True,
"usage_count": 0,
}
# 存入数据库
self.db.execute(
"INSERT INTO api_keys (key_hash, key_id, metadata) VALUES (?, ?, ?)",
(key_hash, key_id, json.dumps(key_metadata))
)
# 缓存到Redis用于快速验证
self.redis.setex(
f"apikey:{key_hash}",
86400, # 24小时缓存TTL
json.dumps(key_metadata)
)
return {
"api_key": full_key, # 仅向用户展示一次
"key_id": key_id, # 用于引用/管理
"scopes": key_metadata["scopes"],
"expires_at": key_metadata["expires_at"],
}
def validate_key(self, api_key):
"""验证API密钥并返回其元数据。"""
key_hash = hashlib.sha256(api_key.encode()).hexdigest()
# 优先检查Redis缓存
cached = self.redis.get(f"apikey:{key_hash}")
if cached:
metadata = json.loads(cached)
else:
# 回退到数据库
row = self.db.execute(
"SELECT metadata FROM api_keys WHERE key_hash = ?",
(key_hash,)
).fetchone()
if not row:
return None, "invalid_key"
metadata = json.loads(row[0])
# 刷新缓存
self.redis.setex(f"apikey:{key_hash}", 86400, row[0])
# 验证检查
if not metadata.get("is_active"):
return None, "key_revoked"
if metadata.get("expires_at"):
if datetime.fromisoformat(metadata["expires_at"]) < datetime.utcnow():
return None, "key_expired"
# 更新最后使用时间
metadata["last_used"] = datetime.utcnow().isoformat()
metadata["usage_count"] = metadata.get("usage_count", 0) + 1
self.redis.setex(f"apikey:{key_hash}", 86400, json.dumps(metadata))
return metadata, "valid"
def revoke_key(self, key_id):
"""立即吊销API密钥。"""
row = self.db.execute(
"SELECT key_hash, metadata FROM api_keys WHERE key_id = ?",
(key_id,)
).fetchone()
if row:
key_hash = row[0]
metadata = json.loads(row[1])
metadata["is_active"] = False
metadata["revoked_at"] = datetime.utcnow().isoformat()
self.db.execute(
"UPDATE api_keys SET metadata = ? WHERE key_id = ?",
(json.dumps(metadata), key_id)
)
# 立即使缓存失效
self.redis.delete(f"apikey:{key_hash}")
return True
return False
def rotate_key(self, old_key_id, grace_period_hours=24):
"""轮换API密钥,提供新旧密钥同时生效的宽限期。"""
old_row = self.db.execute(
"SELECT key_hash, metadata FROM api_keys WHERE key_id = ?",
(old_key_id,)
).fetchone()
if not old_row:
return None, "key_not_found"
old_metadata = json.loads(old_row[1])
# 使用相同设置生成新密钥
new_key_data = self.generate_key(
key_type=old_metadata["key_type"],
owner_id=old_metadata["owner_id"],
scopes=old_metadata["scopes"],
rate_limit=old_metadata["rate_limit"],
ip_allowlist=old_metadata["ip_allowlist"],
)
# 在宽限期后安排旧密钥吊销
revoke_at = datetime.utcnow() + timedelta(hours=grace_period_hours)
old_metadata["scheduled_revocation"] = revoke_at.isoformat()
self.db.execute(
"UPDATE api_keys SET metadata = ? WHERE key_id = ?",
(json.dumps(old_metadata), old_key_id)
)
return {
"new_key": new_key_data,
"old_key_id": old_key_id,
"old_key_revokes_at": revoke_at.isoformat(),
"message": f"旧密钥将在 {grace_period_hours} 小时后吊销"
}, "success"
```
### 步骤2:API密钥验证中间件
```python
from flask import Flask, request, jsonify, g
from functools import wraps
app = Flask(__name__)
def require_api_key(required_scopes=None):
"""验证API密钥并检查范围的中间件。"""
def decorator(f):
@wraps(f)
def wrapped(*args, **kwargs):
# 从请求头提取API密钥
api_key = request.headers.get("X-API-Key")
if not api_key:
# 也检查 Authorization: Bearer <key>
auth_header = request.headers.get("Authorization", "")
if auth_header.startswith("Bearer "):
api_key = auth_header[7:]
if not api_key:
return jsonify({"error": "missing_api_key"}), 401
# 验证密钥
metadata, status = key_manager.validate_key(api_key)
if status != "valid":
return jsonify({"error": status}), 401
# 检查IP白名单
if metadata.get("ip_allowlist"):
client_ip = request.remote_addr
if client_ip not in metadata["ip_allowlist"]:
return jsonify({"error": "ip_not_allowed"}), 403
# 检查范围
if required_scopes:
key_scopes = set(metadata.get("scopes", []))
if not key_scopes.intersection(required_scopes):
return jsonify({"error": "insufficient_scope"}), 403
# 将元数据附加到请求上下文
g.api_key_metadata = metadata
return f(*args, **kwargs)
return wrapped
return decorator
@app.route('/api/v1/data', methods=['GET'])
@require_api_key(required_scopes=["read", "admin"])
def get_data():
return jsonify({"data": "敏感信息"})
@app.route('/api/v1/data', methods=['POST'])
@require_api_key(required_scopes=["write", "admin"])
def create_data():
return jsonify({"created": True})
```
### 步骤3:自动化密钥泄露检测
```bash
# 使用gitleaks扫描GitHub仓库中的泄露API密钥
gitleaks detect --source=/path/to/repo --config=gitleaks.toml --report-path=leaks.json
# 用于API密钥前缀检测的自定义gitleaks配置
# gitleaks.toml
cat <<'EOF'
[[rules]]
id = "company-api-key-live"
description = "Company Live API Key"
regex = '''sk_live_[A-Za-z0-9_-]{32,}'''
tags = ["api-key", "live", "critical"]
[[rules]]
id = "company-api-key-test"
description = "Company Test API Key"
regex = '''sk_test_[A-Za-z0-9_-]{32,}'''
tags = ["api-key", "test"]
[[rules]]
id = "company-public-key"
description = "Company Public API Key"
regex = '''pk_live_[A-Za-z0-9_-]{32,}'''
tags = ["api-key", "public"]
EOF
```
```python
# 自动化泄露密钥吊销
import json
def process_leaked_keys(leaks_file):
"""自动吊销在公共仓库中检测到的API密钥。"""
with open(leaks_file) as f:
leaks = json.load(f)
for leak in leaks:
key_match = leak.get("match", "")
# 从匹配中提取密钥
for prefix in ["sk_live_", "sk_test_", "pk_live_"]:
if prefix in key_match:
start = key_match.index(prefix)
potential_key = key_match[start:start+50] # 最大密钥长度
# 验证并吊销
metadata, status = key_manager.validate_key(potential_key)
if status == "valid":
key_manager.revoke_key(metadata["key_id"])
print(f"[已吊销] 密钥 {metadata['key_id']} 在 {leak.get('file')} 中泄露")
# 通知密钥所有者
notify_owner(metadata["owner_id"], metadata["key_id"], leak)
```
## 核心概念
| 术语 | 定义 |
|------|------------|
| **API密钥(API Key)** | 用于认证API请求的密钥字符串,通常通过请求头或查询参数传递 |
| **密钥哈希(Key Hashing)** | 在数据库中只存储API密钥的哈希值(SHA-256),永不存储明文密钥,类似于密码哈希 |
| **密钥轮换(Key Rotation)** | 在维持宽限期(新旧密钥均有效)的情况下将API密钥替换为新密钥,确保零停机过渡 |
| **密钥范围限制(Key Scoping)** | 将每个API密钥限制到特定端点、HTTP方法、IP范围和速率限制,以最小化影响范围 |
| **密钥前缀(Key Prefix)** | 可识别的前缀(如 sk_live_),使自动化扫描能够在日志、代码和公共仓库中检测泄露密钥 |
| **密钥扫描(Secret Scanning)** | 自动监控仓库、日志和公共来源中暴露的API密钥和凭据 |
## 工具和系统
- **GitHub Secret Scanning**:内置的GitHub功能,检测仓库中暴露的密钥并提醒密钥提供者
- **gitleaks**:使用可定制正则模式检测git仓库中密钥的开源工具
- **truffleHog**:密钥扫描工具,搜索整个git历史中的高熵字符串和已知密钥模式
- **HashiCorp Vault**:企业级密钥管理系统,用于API密钥存储、轮换和动态凭据生成
- **AWS Secrets Manager**:托管的密钥存储服务,支持API密钥和凭据的自动轮换
## 常见场景
### 场景:开发者平台的API密钥安全程序
**背景**:开发者平台提供以API密钥认证的公共API,平台有10,000+个API消费者,每天产生50M+个请求,密钥频繁在公共GitHub仓库中泄露。
**方法**:
1. 实施带前缀的API密钥(sk_live_、sk_test_),使用256位熵用于泄露检测
2. 在数据库中只存储密钥的SHA-256哈希值,在Redis中缓存已验证的密钥
3. 实施按密钥范围限制:每个密钥限定到特定端点、速率限制和可选的IP白名单
4. 构建带24小时宽限期的密钥轮换API,实现无缝过渡
5. 与GitHub Secret Scanning集成,在数分钟内自动检测和吊销泄露的密钥
6. 在CI/CD管道中运行gitleaks,防止密钥首先被提交
7. 实施异常检测:对从异常IP使用或具有异常流量模式的密钥发出告警
8. 添加密钥过期策略:所有密钥在365天后过期,并提前30天通知
**注意事项**:
- 在数据库中以明文存储API密钥(应使用SHA-256哈希)
- 使用可预测或低熵的密钥生成(应使用加密安全随机生成器)
- 未实施密钥前缀,导致无法在自动化扫描中识别泄露密钥
- 允许API密钥出现在URL查询参数中,导致密钥泄露在日志、浏览器历史和Referer头中
- 未实施按密钥速率限制,允许单个受损密钥滥用整个API
## 输出格式
```
## API密钥安全实施报告
**平台**: Developer API v3
**总活跃密钥数**: 12,450
**日密钥验证次数**: 5200万
### 安全控制
| 控制措施 | 实施方式 | 状态 |
|---------|---------------|--------|
| 密钥熵 | 256位(secrets.token_urlsafe(32)) | 已实施 |
| 密钥格式 | sk_live_/sk_test_ 前缀 | 已实施 |
| 存储 | SHA-256哈希,Redis缓存 | 已实施 |
| 范围限制 | 按密钥的端点/IP/速率限制 | 已实施 |
| 轮换 | 24小时宽限期API | 已实施 |
| 过期 | 最大TTL 365天 | 已实施 |
| 泄露检测 | GitHub Secret Scanning + gitleaks | 活跃 |
| 自动吊销 | 泄露密钥5分钟内吊销 | 活跃 |
### 密钥泄露统计(过去30天)
- 公共仓库中检测到的密钥: 23个
- 平均吊销时间: 3.2分钟
- CI/CD预提交检测到的密钥: 7个(已阻断)
```Related Skills
triaging-security-incident
使用 NIST SP 800-61r3 和 SANS PICERL 框架对安全事件进行初始分类,确定严重性、范围和所需响应行动。 按类型对事件分类,根据业务影响分配优先级,并路由到相应的响应团队。适用于事件分类、 安全告警分类、严重性评估、事件优先级排序或初始事件分析等请求场景。
triaging-security-incident-with-ir-playbook
使用结构化 IR Playbook 对安全事件进行分类和优先排序,确定严重性、分配响应团队并启动适当的响应程序。
triaging-security-alerts-in-splunk
在 Splunk Enterprise Security 中对安全告警进行分类,通过 SPL 查询和事件审查(Incident Review) 仪表板对重要事件进行严重性分类、调查、关联相关遥测并做出升级或关闭决策。 适用于 SOC 分析师需要处理关联搜索产生的告警队列、确定调查优先级, 或需要为交接给二/三级分析师记录分类决策时。
testing-websocket-api-security
测试 WebSocket API 实现中的安全漏洞,包括 WebSocket 升级时缺少身份认证、跨站 WebSocket 劫持(Cross-Site WebSocket Hijacking,CSWSH)、通过 WebSocket 消息进行的注入攻击、输入校验不足、通过消息泛洪实施拒绝服务,以及通过 WebSocket 帧造成的信息泄露。测试人员使用 Burp Suite 拦截 WebSocket 握手和消息,构造恶意 payload,并测试 WebSocket 通道上的授权绕过。适用于 WebSocket 安全测试、WS 渗透测试、CSWSH 攻击或实时 API 安全评估相关请求。
testing-jwt-token-security
在安全测试活动中,评估 JSON Web Token(JWT)实现中的密码学弱点、算法混淆攻击和授权绕过漏洞。
testing-api-security-with-owasp-top-10
使用自动化和手工测试技术,针对 OWASP API 安全 Top 10 风险对 REST 和 GraphQL API 端点进行系统性评估。
performing-wireless-security-assessment-with-kismet
使用 Kismet 通过被动射频监控进行无线网络安全评估,检测流氓接入点(Rogue AP)、隐藏 SSID、弱加密和未授权客户端。
performing-ssl-tls-security-assessment
使用 sslyze Python 库评估 SSL/TLS 服务器配置,评估加密套件、证书链、协议版本、HSTS 头部,以及 Heartbleed 和 ROBOT 等已知漏洞。
performing-soap-web-service-security-testing
通过分析 WSDL 定义,测试 XML 注入(XML Injection)、XXE、WS-Security 绕过和 SOAPAction 欺骗,对 SOAP Web 服务执行安全测试。
performing-serverless-function-security-review
对 AWS Lambda、Azure Functions 和 GCP Cloud Functions 中的无服务器函数(Serverless Function)执行安全审查,识别过度宽松的执行角色(Execution Role)、不安全的环境变量、注入漏洞和缺失的运行时保护措施。
performing-scada-hmi-security-assessment
对 SCADA 人机界面(HMI, Human-Machine Interface)系统进行安全评估,识别基于 Web 的 HMI、瘦客户端配置、认证机制以及 HMI 与 PLC 之间通信信道中的漏洞,符合 IEC 62443 和 NIST SP 800-82 指南要求。
performing-s7comm-protocol-security-analysis
对西门子SIMATIC S7 PLC使用的S7comm和S7CommPlus协议进行安全分析,识别漏洞,包括重放攻击、完整性绕过、未授权的CPU停止命令以及针对S7-300、S7-400、S7-1200和S7-1500控制器弱点的程序下载操控。