必须用signtool.exe签名,因其为微软官方唯一认可工具,支持时间戳(/tr /td)、ev证书硬件调用(/sm)等关键参数,其他工具签发的程序易被smartscreen拒绝或触发uac二次确认。

Windows上C++程序签名必须用signtool.exe
不签名的.exe在Win10/11运行时弹“未知发布者”警告,本质是系统验证Authenticode签名。微软官方只认signtool.exe(来自Windows SDK或Visual Studio安装目录),其他工具签的可能被SmartScreen拒绝或触发UAC二次确认。
常见错误:用OpenSSL生成自签名证书后直接调用signcode.exe(已弃用)或第三方脚本——Win11会报SignerCertificateNotTrusted错误,根本过不了内核校验。
- 路径示例:
C:\Program Files (x86)\Windows Kits\10\bin\10.0.22621.0\x64\signtool.exe(版本号随SDK更新) - 必须用.pfx格式证书,密码不能含特殊字符(如
@、$会导致cmd解析失败) - 签名前先用
signtool verify /pa yourapp.exe检查是否已签名,避免重复签名导致校验失败
签名命令里/v /tr /td三个参数缺一不可
Win10 1809之后强制要求时间戳(timestamping),否则证书过期后程序立即失效;/tr指定RFC 3161时间戳服务器地址,/td指定哈希算法,这两项漏掉会导致签名被识别为“无效时间戳”,UAC弹窗仍会出现。
典型正确命令:
signtool sign /v /n "Your Company Inc" /tr http://timestamp.digicert.com /td sha256 /f cert.pfx /p "password" yourapp.exe
-
/v:输出详细日志,能立刻看到Succeeded还是Error: No certificate found -
/tr必须用HTTP而非HTTPS(DigiCert和Sectigo的RFC 3161服务只支持HTTP端点) -
/td sha256:Win11要求SHA-256,SHA-1会被拒绝(报错SignerCertificateNotValid)
代码中嵌入版本信息影响签名完整性
如果用rc资源文件定义VS_VERSION_INFO,编译后资源数据会参与PE校验和计算。签名后若再用verpatch或Resource Hacker修改版本号,签名立即失效——Explorer右键属性里“数字签名”标签页变灰,双击提示Signature is corrupted or invalid。
- 版本信息必须在签名前固化:改完
.rc→ rebuild → 再signtool sign - CI流程中注意:Git自动替换$Revision$等关键字会导致每次构建产物哈希不同,签名失效
- 调试版和发布版必须用同一份资源编译,否则
signtool verify /pa会提示Signer certificate does not match the subject name
EV证书才能绕过SmartScreen首次运行拦截
普通OV证书(如DigiCert Standard)只能消除“未知发布者”弹窗,但首次运行仍卡在SmartScreen白屏警告。只有硬件绑定的EV代码签名证书(如Sectigo EV或DigiCert EV)能触发微软自动学习机制,通常24小时内放行。
- EV证书私钥存在USB令牌里,
signtool需额外加/sm参数调用证书存储 - 申请EV证书要提供营业执照+银行流水+视频认证,周期2周起,别指望临时解决
- 测试阶段可用
signtool sign /debug打调试签名,但仅限本地测试——上传到任何公开渠道都会被SmartScreen拦截
真正绕过警告的关键不是技术动作多快,而是证书类型和首次分发渠道是否匹配微软信任链。小团队发安装包,最稳妥的是先用OV证书签,再通过Microsoft Partner Center提交应用以加速信誉积累。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











