李德虎 發表於 2025-10-11 07:14:00

SignTool 使用 SafeNet eToken 硬证书进行代码签名

<p>根据CA/B联盟国际标准要求,从 2022 年 11 月 15 日起,即使是 OV 代码签名证书,也需要将私钥存储在FIPS140-2 Level2、Common Criteria EAL4级以上或者同等认证级别的硬件,如 USB 令牌、硬件安全模块 HSM 等。原本之前只有 EV 证书才有此要求,现在代码签名也需要如此。我司购买的证书刚好最近差不多快过期了,续签的证书从原本的很方便的 PFX 软证书,换成使用带 HSM 硬件设备的硬证书</p>
<p>换成带 HSM 硬件设备的硬证书之后,依然可以使用 SignTool 进行自动化签名。和之前的软证书 PFX 文件只有命令行参数的差别了。本文将记录如何修改 SignTool 签名命令适配硬证书</p>
<p>我所在的团队是从天威诚信购买的证书,没有议价,稍贵。好在他们的售后服务还不错,会给一些指导,还算值这个价钱。但天威诚信推荐的是用他们的 iTrusSignTool.exe 工具,而非微软官方提供的 SignTool 工具,不利于我的自动化打包平台接入</p>
<p>好在天威诚信购买的证书使用的是 SafeNet 工具,依然可以从堆栈网找到 <code>SafeNet eToken</code> 的 SignTool 命令行签名方法,整个过程不会被弹出要求输入密码的对话框。堆栈网上给的是 EV 证书签名的方法,且也没有中文截图。为了防止其他伙伴踩坑,我重新跑了一遍,编写了本文,包含详细的步骤,步骤里包含中文和英文界面的截图。详细堆栈网的地址是: https://stackoverflow.com/questions/17927895/automate-extended-validation-ev-code-signing-with-safenet-etoken/47894907#47894907</p>
<p>先使用天威诚信供应商提供的口令和安装方法进行安装,这个步骤完成按照他们的文档就可以了,十分简单。唯一需要小心的是,这个过程里面不能使用远程桌面连接,哪怕用向日葵都可以,尽管在打包服务器部署向日葵是十分不安全的</p>
<p>详细配置文档请参阅 天威诚信代码签名证书安装配置指南(Digicert) 代码签名部署文档</p>
<p>如从其他供应商购买,还请自行参阅其他供应商提供的方法。如 https://www.geocerts.com/support/digicert-usb-etoken-installation-guide</p>
<p>完成证书下载任务之后,接下来即可进行本文的步骤了。本文以下步骤里面,我所有写入的我的密码等,都不是我所在团队真正使用的密码,还请大家不用担心我泄露密码,但却都是符合真实格式的内容,便于大家明确了解各个参数应该从哪里拿到</p>
<p>0 首先点击齿轮键进入高级模式,其高级模式界面如下</p>

<p><img src="https://img2024.cnblogs.com/blog/1080237/202510/1080237-20251011071359813-1319593966.png"></p>

<p><img src="https://img2024.cnblogs.com/blog/1080237/202510/1080237-20251011071401030-917616188.png"></p>
<p>1 导出证书为 Codesign.cer 文件。右击对应的证书,选择导出,保存到文件即可。导出的 cer 格式的证书文件将不包含私钥,需要使用以下步骤获取 CSP 名和其对应的私钥容器名参数才能让 SignTool 从硬件设备获取私钥用于签名</p>

<p><img src="https://img2024.cnblogs.com/blog/1080237/202510/1080237-20251011071401523-446592679.png"></p>

<p><img src="https://img2024.cnblogs.com/blog/1080237/202510/1080237-20251011071401873-994693772.png"></p>
<p>2 记住证书的容器名。将其记录到记事本里,后续命令将会用到。如我的是 Container name 容器名是 <code>p11#59336aa23069996b</code></p>

<p><img src="https://img2024.cnblogs.com/blog/1080237/202510/1080237-20251011071402248-1081025170.png"></p>

<p><img src="https://img2024.cnblogs.com/blog/1080237/202510/1080237-20251011071402613-832214469.png"></p>
<p>3 获取设备的 CSP 名和读卡器名称</p>
<p>读卡器名称:</p>

<p><img src="https://img2024.cnblogs.com/blog/1080237/202510/1080237-20251011071402950-1542187948.png"></p>

<p><img src="https://img2024.cnblogs.com/blog/1080237/202510/1080237-20251011071403266-1328796997.png"></p>
<p>CSP 名:</p>
<p>CSP 名和读卡器名称在相同一页,只是内容比较多,需要滚动一下滚动条才能看到。额外地,在菜单栏也提供了复制的按钮,不需要真自己一个个字符抄</p>

<p><img src="https://img2024.cnblogs.com/blog/1080237/202510/1080237-20251011071403650-1157165061.png"></p>
<p>如我的读卡器名 reader 为 <code>SafeNet Token JC 0</code></p>
<p>如我的 CSP 名为 <code>eToken Base Cryptographic Provider</code></p>
<p>4 拼接私钥容器名参数</p>
<p>eToken CSP 具有隐藏(或者至少没有广泛宣传)的功能,可以从容器名称中解析出令牌密码。尽管 https://stackoverflow.com/questions/17927895/automate-extended-validation-ev-code-signing-with-safenet-etoken/47894907#47894907 说明包含四个可选项,但实际我测试了,最稳妥的是最为复杂的写法项</p>
<p>为了让我的博客引擎开森,我将以下代码的两个连在一起的花括号替换为全角的花括号。自己使用的时候,还请替换全角的花括号为半角的花括号</p>
<pre><code>=ContainerName
</code></pre>
<p>其各个参数含义如下</p>
<ul>
<li>reader: 读卡器名。第 3 步获取到的,如我的是 <code>SafeNet Token JC 0</code></li>
<li>password: 下载证书过程中,自己设置的证书密码,如我的是 <code>Lindexi123</code></li>
<li>ContainerName: 证书的容器名。第 2 步获取的,如我的是 <code>p11#59336aa23069996b</code></li>
</ul>
<p>重点说明,以上格式的两个连续花括号是必需的部分,这属于语法的一部分,还请不要省略</p>
<p>拼接之后的私钥容器名参数如下</p>
<pre><code>/k "=p11#59336aa23069996b"
</code></pre>
<p>5 完全的签名参数</p>
<p>按照微软的官方文档,可以知道其核心参数如下</p>
<ul>
<li><code>/f</code> : 导出的 Codesign.cer 签名证书文件,此证书文件没有包含私钥。私钥是存放在硬件设备里面。如后续步骤错误,将收到 SignTool Error: No private key is available 错误提示</li>
<li><code>/csp</code> :传入从步骤 3 获取的 CSP 名。只有 csp 不配合 <code>/k</code> 参数,则将收到 SignTool Error: The /csp option requires the /k option. 错误</li>
<li><code>/k</code> : 从步骤 4 拼接到的。等同于 <code>/kc</code> 参数,即写 <code>/k</code> 或 <code>/kc</code> 都可以</li>
</ul>
<p>非核心的日常参数如下,以下参数相对固定,正常不用更改</p>
<ul>
<li><code>/td</code> :将此选项与 <code>/tr</code> 选项一起使用可请求 RFC 3161 时间戳服务器使用的摘要算法。正常现在只能用 <code>/td sha256</code></li>
<li><code>/tr</code> :指定 RFC 3161 时间戳服务器的 URL 地址。如用 digi 的服务器 <code>/tr http://timestamp.digicert.com</code></li>
<li><code>/fd</code> :指定要用于创建文件签名的文件摘要算法。正常现在只能用 <code>/fd sha256</code> 或 <code>/fd sha1</code>
<ul>
<li>额外说明,正常只需带上 <code>/fd sha256</code> 即可。如需让 win7 兼容识别,则再跑一次签名,传入 <code>/fd sha1</code> 和 <code>/as</code> 参数即可</li>
</ul>
</li>
<li><code>/as</code> :追加此签名。如果不存在主签名,则改为使此签名成为主签名</li>
</ul>
<p>以下是我的示例签名命令,对 Test1.exe 文件进行签名</p>
<pre><code>SignTool sign /f "Codesign.cer" /td sha256 /as /fd sha256 /tr http://timestamp.digicert.com /csp "eToken Base Cryptographic Provider" /k "=p11#59336aa23069996b" Test1.exe
</code></pre>
<p>以上签名命令里面,为了让我的博客引擎开森,我将两个连在一起的花括号替换为全角的花括号,还请自行替换为半角花括号。额外地,大家所设置的密码,即 <code>Lindexi123</code> 部分,以及证书的容器名,即 <code>p11#59336aa23069996b</code> 部分,都是和我不相同的,还请大家自行替换为自己的密码和证书的容器名</p>
<p>以上签名命令里面,证书文件写的是相对路径,如遇到证书找不到的问题,还请自行修改为你的正确证书文件路径。证书文件 <code>/f</code> 参数也可传入绝对路径,正常在打包过程中,传入绝对路径更好,避免工作路径干扰</p>
<p>在此过程里面,都需要保持签名设备没有远程桌面 RDP 连接,否则将会签名失败。如签名成功,将会看到大概如下的控制台输出内容</p>
<pre><code>Done Adding Additional Store
Successfully signed: Test1.exe
</code></pre>
<p>签名成功之后,右击被签名的文件的属性,可以从数字签名界面看到签名内容。大家可以先尝试命令行参数,确定能够正常签名之后,再接入到自己的打包平台里面。对每个文件的签名,也只有传入的文件路径不相同而已,其他参数都是一样的,换句话说只要自己能拼接出一次正确的命令参数,接下来的其他文件的签名都可以复用这些参数</p>
<p>为了防止有伙伴不知道从哪获取 SignTool 工具,我这里给出正确的获取 SignTool 方法。敲黑板,正常安装 VisualStudio 2022 或更高版本,即可在你的电脑上找到官方的 SignTool 工具,可别在网上随便下载。证书这东西可是非常机密且重要的,你可以理解为你的公章,被盗用了会有法律风险。证书可是你司签了合同才能购买的哦,如果被木马伪装的工具偷走了,那可就麻烦了哦</p>
<p>正常应该是在 <code>C:\Program Files (x86)\Windows Kits\10\bin\&lt;SDK 版本号&gt;\&lt;x86 或 x64&gt;\signtool.exe</code> 路径里。获取确切路径的方法如下</p>
<p>从开始菜单打开 Developer Command Prompt for VS 2022 命令行工具,先敲下 SignTool 回车,确保工具已经就绪。随后再输入 <code>where SignTool</code> 即可获取到工具所在路径</p>
<pre><code>C:\Program Files\Microsoft Visual Studio\2022\Professional&gt;where SignTool
C:\Program Files (x86)\Windows Kits\10\bin\10.0.26100.0\x86\signtool.exe
</code></pre>
<p>如果打开的 Developer Command Prompt for VS 2022 命令工具是 PowerShell 版本的,还请先输入 cmd 进入到 cmd 里,再输入 <code>where SignTool</code> 获取其路径</p>
<pre><code>**********************************************************************
** Visual Studio 2022 Developer PowerShell v17.14.17
** Copyright (c) 2025 Microsoft Corporation
**********************************************************************
PS C:\Program Files\Microsoft Visual Studio\2022\Professional&gt; cmd
Microsoft Windows [版本 10.0.26100.6899]
(c) Microsoft Corporation。保留所有权利。

C:\Program Files\Microsoft Visual Studio\2022\Professional&gt;where SignTool
C:\Program Files (x86)\Windows Kits\10\bin\10.0.26100.0\x64\signtool.exe
</code></pre>
<p>参考文档</p>
<ul>
<li>Digicert代码签名证书助手操作指南 代码签名部署文档</li>
<li>天威诚信代码签名证书安装配置指南(Digicert) 代码签名部署文档</li>
<li>https://www.gworg.com/code/1627.html</li>
<li>使用 SignTool 对文件进行签名 - Win32 apps Microsoft Learn</li>
<li>SignTool - Win32 apps - Microsoft Learn</li>
</ul>


</div>
<div id="MySignature" role="contentinfo">
    <p>博客园博客只做备份,博客发布就不再更新,如果想看最新博客,请访问 https://blog.lindexi.com/</p>

<p>如图片看不见,请在浏览器开启不安全http内容兼容</p>

<img alt="知识共享许可协议" style="border-width: 0" src="https://licensebuttons.net/l/by-nc-sa/4.0/88x31.png"><br>本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名[林德熙](https://www.cnblogs.com/lindexi)(包含链接:https://www.cnblogs.com/lindexi ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我[联系](mailto:lindexi_gd@163.com)。<br><br>
来源:https://www.cnblogs.com/lindexi/p/19134167
頁: [1]
查看完整版本: SignTool 使用 SafeNet eToken 硬证书进行代码签名