让 AI 先画出密码学地图:面向 2029 的后量子迁移方法

2026-09-29 33 预计阅读时间: 1 分钟
来源: blog.cloudflare.com AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:11 分钟

后量子迁移并不只是把某个 RSA 调用替换成新算法。真正棘手的是:组织往往不知道密码学究竟藏在哪些服务、依赖、配置和协议里,也不清楚一次替换会影响多少上下游系统。

CryptoLabe 的方向正是解决这个问题:用内部 AI 工具发现代码库中的密码学使用点,梳理依赖关系,并为 2029 年前完成全面迁移提供持续可更新的路线图。这个思路的重要之处,不是让模型自动“发明”密码方案,而是让 AI 帮工程团队建立一份可验证的密码学资产清单。

后量子迁移的第一步不是选算法,而是建立资产地图

大型代码库里的密码学通常不只出现在显眼的加密函数中。它可能存在于:

  • 直接调用的哈希、签名、密钥交换和加密 API;
  • TLS、SSH、证书和密钥库配置;
  • JWT、软件包签名、固件验证和代码签名流程;
  • 数据库驱动、服务网格、消息队列等间接依赖;
  • 第三方 SDK、系统镜像和外部托管服务;
  • 文档、测试夹具、部署脚本以及基础设施配置。

因此,扫描结果不能只回答“哪里出现了 RSA”。它至少还应记录:

  1. 位置:仓库、文件、行号、服务和负责人;
  2. 用途:签名、密钥交换、静态数据加密还是兼容旧协议;
  3. 依赖:算法来自应用代码、运行时、操作系统还是外部服务;
  4. 暴露期限:被保护的数据需要保密多久;
  5. 迁移约束:协议兼容性、证书体系、硬件支持和性能预算;
  6. 证据与置信度:工具为什么认为这里存在密码学调用。

这一点尤其关键。AI 给出的分类如果没有文件路径、代码片段和依赖证据,就很难进入安全评审,也无法可靠地生成改造任务。

AI 适合归类和串联,不应独自做密码决策

传统静态扫描擅长匹配确定的 API 和配置项,却不一定能理解业务语义。例如,同一个 SHA-256 调用可能用于内容去重、密码存储、证书指纹或数字签名。它们的迁移优先级和处理方式完全不同。

AI 可以放在确定性扫描之后,承担三类工作:

  • 根据调用上下文判断密码学用途;
  • 把代码、配置、服务目录和依赖清单串成关系图;
  • 将技术发现转换为团队、里程碑和阻塞项。

但模型输出应被视为候选结论,而不是最终安全判断。一个稳妥的处理链路可以是:

仓库与制品清单
    ↓
规则扫描 / AST / 依赖解析
    ↓
带证据的密码学发现记录
    ↓
AI 分类、去重与依赖推断
    ↓
人工安全评审
    ↓
迁移任务、测试和验收证据

向模型提供的信息也应经过控制。不要把私钥、令牌、完整生产配置或不允许外发的源代码直接提交给公共模型。内部部署、访问控制、提示词与响应审计、数据保留策略,都是这类工具本身必须具备的安全边界。

可以这样实践:先做一个可审计的代码库扫描器

下面的 Python 脚本只使用标准库,可以扫描常见源码和配置文件,输出带文件位置和匹配证据的 JSON。它不是完整的后量子评估器,而是一个适合作为 CryptoLabe 类工作流入口的最小原型。

将代码保存为 crypto_inventory.py:

#!/usr/bin/env python3
import argparse
import json
import re
from pathlib import Path

RULES = {
    "legacy_hash": re.compile(r"\b(md5|sha1|hashlib\.md5|hashlib\.sha1)\b", re.I),
    "public_key_crypto": re.compile(r"\b(RSA|ECDSA|ECDH|Ed25519|X25519)\b", re.I),
    "tls_config": re.compile(r"\b(TLSv1(?:\.0|\.1|\.2|\.3)?|cipher_suites?|ssl_protocols?)\b", re.I),
    "certificate_or_key": re.compile(r"\b(X\.509|BEGIN CERTIFICATE|BEGIN (?:RSA |EC )?PRIVATE KEY)\b", re.I),
    "crypto_library": re.compile(r"\b(cryptography|pycryptodome|openssl|libsodium|bouncycastle)\b", re.I),
}

EXTENSIONS = {
    ".py", ".go", ".java", ".js", ".ts", ".rs", ".c", ".cc", ".cpp", ".h",
    ".yaml", ".yml", ".json", ".toml", ".ini", ".conf", ".xml", ".gradle"
}
SKIP_DIRS = {".git", "node_modules", "vendor", "dist", "build", ".venv", "venv"}


def scan(root: Path):
    findings = []
    for path in root.rglob("*"):
        if not path.is_file() or path.suffix.lower() not in EXTENSIONS:
            continue
        if any(part in SKIP_DIRS for part in path.parts):
            continue

        try:
            lines = path.read_text(encoding="utf-8", errors="ignore").splitlines()
        except OSError:
            continue

        for line_number, line in enumerate(lines, start=1):
            for rule_name, pattern in RULES.items():
                matches = sorted({match.group(0) for match in pattern.finditer(line)})
                if matches:
                    findings.append({
                        "rule": rule_name,
                        "file": str(path.relative_to(root)),
                        "line": line_number,
                        "matches": matches,
                        "evidence": line.strip()[:240],
                        "review_status": "unreviewed"
                    })
    return findings


def main():
    parser = argparse.ArgumentParser(description="Create a basic cryptography inventory")
    parser.add_argument("root", nargs="?", default=".", help="Repository root")
    parser.add_argument("-o", "--output", default="crypto-inventory.json")
    args = parser.parse_args()

    root = Path(args.root).resolve()
    findings = scan(root)
    Path(args.output).write_text(
        json.dumps(findings, indent=2, ensure_ascii=False),
        encoding="utf-8"
    )
    print(f"Wrote {len(findings)} findings to {args.output}")


if __name__ == "__main__":
    main()

在目标仓库中运行:

python3 crypto_inventory.py /path/to/repository -o crypto-inventory.json
python3 -m json.tool crypto-inventory.json | less

运行前应根据组织使用的语言、框架和密码库扩充规则。这个脚本采用文本匹配,可能产生误报,也无法发现动态调用、封装后的内部 API 或二进制依赖。生产实现可以进一步接入 AST 分析、软件物料清单(SBOM)、构建图和服务目录。

扫描结果可以交给内部模型进行结构化分类,但提示词应强制模型保留证据并承认不确定性。例如:

你是一名密码学迁移分析助手。
根据输入的扫描记录,判断该发现最可能属于:
1. 数字签名
2. 密钥交换
3. 静态数据加密
4. 传输加密
5. 非安全用途的哈希或校验
6. 无法判断

只返回 JSON。必须包含 category、confidence、reason、required_evidence、suggested_owner。
不得根据算法名称直接断言业务用途;证据不足时选择“无法判断”。
不要提出自创密码算法,也不要声称某个替代方案已经通过组织安全审批。

从发现数量转向可执行的迁移队列

单纯统计“发现了多少个 RSA”并不能衡量迁移进度。更有价值的是给每条记录建立状态机,例如:

asset_id: payments-api/tls-client
owner: payments-platform
purpose: service-authentication
current_mechanism: certificate-based TLS
source_evidence:
  repository: payments-api
  file: config/tls.yaml
  line: 18
depends_on:
  - internal-ca
  - edge-gateway
migration:
  status: assessment-required
  target_date: 2027-06-30
  compatibility_test: not-started
  rollback_plan: required
review:
  human_verified: false
  confidence: medium

这里的日期、负责人和机制只是示例,需要替换为实际组织数据。采用统一记录格式后,团队才能回答更实际的问题:哪些系统没有负责人、哪些迁移被外部厂商阻塞、哪些数据面临“现在收集、未来解密”的长期风险,以及哪些改动必须以混合或分阶段方式部署。

面向 2029,工具建设应服务于持续迁移

密码学资产不是一次扫描就能固定下来的。新服务、依赖升级、证书策略和云平台配置都会不断改变结果。因此,CryptoLabe 这类工具更适合被建设成持续控制面,而不是一次性的报告生成器。

落地时可以检查以下几项:

  • 扫描是否覆盖源码、配置、依赖、制品和托管服务;
  • 每个结论是否保留可复查的证据;
  • AI 输出是否有置信度、人工复核和审计记录;
  • 清单是否连接服务负责人和真实依赖关系;
  • 迁移任务是否包含互操作测试、性能测试和回滚方案;
  • CI 是否能发现新引入的旧式或未批准密码机制;
  • 是否避免把秘密材料和敏感代码泄露给模型供应商。

后量子迁移的难点不只是密码学本身,更是跨代码库、平台和组织边界的协调。AI 最有价值的角色,是把分散证据整理成一张不断更新的地图;算法选择、风险接受和上线批准,仍然需要密码学专家、系统负责人和安全团队共同完成。


相关推荐