aslancarlos/codesign-workshop

GitHub: aslancarlos/codesign-workshop

一个交互式终端工坊,通过 PKCS#11 接口现场演示云端 HSM 支持的代码签名全流程,涵盖密钥保护、职责分离与治理审计等安全特性。

Stars: 0 | Forks: 0

# 代码签名工坊 (PKCS#11 → 云端 HSM) [![CI](https://static.pigsec.cn/wp-content/uploads/repos/2026/06/ce8a0b1006212841.svg)](https://github.com/aslancarlos/codesign-workshop/actions/workflows/shellcheck.yml) [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) [![Made with Bash](https://img.shields.io/badge/made%20with-bash-1f425f.svg)](https://www.gnu.org/software/bash/) [![ShellCheck](https://img.shields.io/badge/shellcheck-clean-brightgreen.svg)](https://www.shellcheck.net/) [![Languages: PT · ES](https://img.shields.io/badge/UI-PT%20%C2%B7%20ES-orange.svg)](#) 这是一个交互式、菜单驱动的终端**工坊**,它通过 **PKCS#11** 接口针对云端 Code Sign Manager 服务(例如 **CyberArk Code Sign Manager – SaaS**,前身为 *Venafi CodeSign Protect*),现场演示了**由 HSM 支持的代码签名**是如何工作的。 这个工坊的核心目的是一步步**证明**在签署软件时至关重要的安全特性: - 🔒 **私钥永不离开 HSM。** 工具仅发送 *hash*;签名结果随后返回。工坊甚至会尝试导出密钥并展示 HSM 拒绝该操作的过程。 - ✍️ **真实、可验证的签名。** 它使用 `jarsigner` 对真实的 `.jar` 进行签名,并使用 `openssl` 生成真实的 CMS/PKCS#7 签名,然后使用它们原生的工具对两者进行验证。 - 👥 **职责分离。** 作为项目*所有者*并**不**授予签名权限——只有*授权的签名者*身份才能使用这些密钥。 - 🧾 **治理与不可抵赖性。** 它通过平台 API 获取每个密钥的签名计数器,并在本地保留其执行的每个签名的详细日志(时间戳、身份、密钥、工具、制品、SHA-256)。 交互式 UI 提供**葡萄牙语 和西班牙语**版本。 本文档为英文版本。 ## 目录 - [工作原理](#how-it-works) - [环境要求](#requirements) - [配置](#configuration) - [运行工坊](#running-the-workshop) - [具体步骤](#the-steps) - [架构](#architecture) - [安全说明](#security-notes) - [故障排除](#troubleshooting) - [贡献](#contributing) - [许可证](#license) ## 工作原理 构建机器上的签名工具与 **PKCS#11 module**(Code Sign Manager 客户端库,例如 `venafipkcs11.so`)进行通信。该模块将 hash 转发给云服务,云服务在 **HSM** 内部执行签名操作并返回签名。客户端上永远不会存在私钥材料。 ``` build machine PKCS#11 module Cloud HSM (jarsigner/openssl) ──hash──► (vendor .so) ──hash──► [ private key ] ◄─sig─── ◄─sig──── 🔒 never leaves ``` 身份通过 **grant**(通过客户端的 `login` 获取)向服务进行身份验证。只有作为包含签名密钥项目的**授权签名者**,这些身份才能看到密钥。 ## 环境要求 该工坊是一个可移植的 `bash` 脚本。要体验**每一个**步骤,你需要: | 工具 | 用于 | 必需 | |------|----------|----------| | `bash` (4+) | 工坊本身 | ✅ | | Code Sign Manager **PKCS#11 client**(提供 `pkcs11config` + `.so`) | 登录、列出、签名、获取证书 | ✅ | | 带有 **pkcs11 engine**(`libpkcs11.so` / `engines-3/pkcs11.so`)的 `openssl` (3.x) | CMS 签名与验证 | 可选步骤 | | `jarsigner` + `keytool` (JDK 11+) | 真实的 JAR 签名及“密钥保留在 HSM 中”的证明 | 可选步骤 | | `python3` | 格式化 API/清单输出 | 可选步骤 | | `curl` | 基于 API 的步骤(计数、签名者) | 可选步骤 | 如果缺少某个工具,相应步骤会优雅降级并给出提示;工坊的其余部分仍会继续运行。 ## 配置 所有内容都通过**环境变量**进行配置——没有硬编码的身份、密钥、租户或标签。复制模板并进行调整: ``` cp .env.example .env # 编辑 .env,然后: set -a; . ./.env; set +a ./codesign-workshop.sh ``` | 变量 | 默认值 | 描述 | |----------|---------|-------------| | `CLIENT_ID` | *(空)* | 用于登录的服务账号 UUID(登录步骤必需) | | `KEYFILE` | `$HOME/.codesign/service_account.key` | 服务账号私钥 (PEM) | | `API_TOKEN_FILE` | `$HOME/.codesign/api_token` | 包含 API 密钥的文件;启用基于 API 的步骤 | | `LABEL_SIGN` | `signing-key` | 签名密钥标签(如 `pkcs11config list` 所示) | | `LABEL_CERT` | `$LABEL_SIGN` | 要下载的证书标签 | | `PROJECT` | `my-project` | Code Sign 项目名称(用于 API 查询和控制台提示) | | `IDENTITY` | `signer` | 签名身份的友好显示名称 | | `TENANT` | *(空)* | 租户 / URL 前缀(设置后仅在控制台提示中显示) | | `API_BASE` | `https://api.venafi.cloud` | API 区域基 URL(默认为美国;EU/AU/UK/SG/CA 有所不同) | | `BRAND` | `Machine Identity - Code Signing Workshop` | 横幅 / 标题文本 | | `MODULE` | `/opt/venafi/codesign/lib/venafipkcs11.so` | PKCS#11 module 的路径 | | `ENGINE_SO` | `/usr/lib/x86_64-linux-gnu/engines-3/pkcs11.so` | OpenSSL pkcs11 engine 的路径 | | `PKCS11_PIN` | `1234` | PKCS#11 PIN — 一个虚拟值;真正的认证是云端 grant | | `WORK` | `/tmp/codesign_demo` | 生成制品的工作目录 | | `DEMO_LANG` | *(询问)* | `pt` 或 `es`;如果为空,工坊在启动时会进行询问 | ## 运行工坊 ``` ./codesign-workshop.sh # asks for language, then shows the menu DEMO_LANG=es ./codesign-workshop.sh # start directly in Spanish ``` 从菜单中选择步骤,或按 **`g`** 运行完整的引导脚本 (开场 → 价值回顾)。按 **`l`** 可随时切换语言。 ## 具体步骤 | # | 步骤 | 演示内容 | |---|------|----------------------| | i | 开场 | 业务问题 + 架构图 | | 1 | 前置条件 | 客户端版本和 grant 有效性 | | 2 | 登录 | 以服务账号身份进行认证 (机器身份) | | 3 | 职责分离 | 所有者什么也看不到;授权签名者可以看到密钥 | | 4 | 列出 | 同步到客户端的密钥/证书引用 | | 5 | 密钥保留在 HSM 中 | 导出尝试被**拒绝** (不可提取) | | 6 | 获取证书 | 仅下载公共证书 + 证书链 | | 7 | 签名 JAR | 真实的 `jarsigner` 签名,原生验证 | | 8 | 签名 CMS/PKCS#7 | 真实的 `openssl` 签名 + 往返延迟 | | 9 | 完整性与防篡改 | 正向验证 + 篡改检测 | | 10 | 治理 | 通过 API 获取的核心密钥清单 + 签名者 | | 11 | 签名与日志 | 每个密钥的计数器 + 最后 5 条详细签名记录 | | 12 | 价值回顾 | 证明点 + 合规性映射 | 每个签名步骤(7、8、9)都会打印一张 **ASCII 流程图**,展示工具如何通过 PKCS#11 连接到 HSM,并向步骤 11 中显示的本地会话日志追加一条记录。 ## 架构 请参阅 [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) 了解数据流图和身份/授权模型。 ## 安全说明 请参阅 [`SECURITY.md`](SECURITY.md)。简而言之:切勿提交私钥或 API token;工坊会将生成的制品(以及包含服务账号显示名称和制品 hash 的会话签名日志)写入 `WORK` 目录——体验完成后,请使用菜单中的 *cleanup* 选项将其清理干净。 ## 故障排除 请参阅 [`docs/USAGE.md`](docs/USAGE.md#troubleshooting)。最常见的问题是 `list` 为空:这意味着经过认证的身份不是包含*就绪*密钥项目的**授权签名者**——请在控制台中修复此问题,然后使用 `--force` 重新登录。 ## 开发 本工坊**以模块形式开发**,位于 `src/` 目录下,并**作为单个独立文件** (`codesign-workshop.sh`) 分发,以便可以将其复制到目标机器上运行,无需额外文件。 ``` # 编辑 src/ 下的模块,然后重新生成可分发包: ./build.sh # 验证其是否同步(这是 CI 运行的内容): ./build.sh --check ``` **请勿**手动编辑 `codesign-workshop.sh` ——它是生成的。请参阅 [`CONTRIBUTING.md`](CONTRIBUTING.md#project-layout) 了解模块映射。 ## 贡献 欢迎贡献——请参阅 [`CONTRIBUTING.md`](CONTRIBUTING.md) 和 [`CODE_OF_CONDUCT.md`](CODE_OF_CONDUCT.md)。 ## 许可证 [MIT](LICENSE)。
标签:Bash, HSM, PKCS#11, 代码签名, 安全培训, 安全测试工具, 密码学, 应用安全, 手动系统调用, 逆向工具