go版本增加软件签名
This commit is contained in:
1 parent
c4b5a4ae41
commit
d076291a62
4 files changed
+297
No files matched your search
@@ -11,3 +11,7 @@
|
||||
|
||||
# 测试二进制
|
||||
*.test
|
||||
|
||||
# 代码签名证书与工具(私钥材料,绝不入库)
|
||||
/certs/
|
||||
/tools/
|
||||
+224
@@ -0,0 +1,224 @@
|
||||
# Excel 关键字搜索工具 —— 代码签名说明
|
||||
|
||||
Windows 发布版可执行文件(`.exe`)的 **Authenticode 代码签名** 与 **时间戳** 全流程说明。
|
||||
用于解决打包产物被 Symantec 等杀软误报(如 `Heur.AdvML.B`)的问题,也是正式对外分发的标准动作。
|
||||
|
||||
> 适用对象:`cmd/desktop`、`cmd/webui`、`cmd/searcher` 三个入口编译出的全部 exe。
|
||||
|
||||
---
|
||||
|
||||
## 一、为什么需要签名
|
||||
|
||||
| 现象 | 原因 | 签名的作用 |
|
||||
|---|---|---|
|
||||
| 杀软误报 `Heur.AdvML.B` | 无签名 + 符号剥离(`-s -w`)的结构特征,被启发式 ML 视为可疑 | 带 Authenticode 签名的 exe 结构显著不同,评分大幅下降 |
|
||||
| 无签名 exe 被拦截/隔离 | 系统信任模型默认不信任"未知来源"程序 | 签名建立发布者身份,提高系统信任度 |
|
||||
|
||||
**自签名证书的现实效果**:自签名证书**不链到公共信任根**,Symantec/Windows 不会"信任"该签名;但签名块本身已让 exe 脱离"无签名"形态,绝大多数启发式 ML 误报可消除。若要彻底消除全部杀软误报并显示绿色签名,需购买公共 OV/EV 证书(见「七、升级到公共证书」)。
|
||||
|
||||
---
|
||||
|
||||
## 二、相关文件与目录结构
|
||||
|
||||
```
|
||||
go/
|
||||
├── sign.bat # 一键签名脚本(纳入版本控制)
|
||||
├── certs/ # 签名证书(已 gitignore,私钥材料,绝不入库/分发)
|
||||
│ ├── codesign.crt # 自签名证书(公开部分)
|
||||
│ ├── codesign.key # 私钥(⚠️ 最高机密)
|
||||
│ └── codesign.pfx # 证书+私钥打包(签名工具实际使用)
|
||||
└── tools/ # 签名工具(已 gitignore,可重新下载)
|
||||
└── osslsigncode/ # osslsigncode 便携版(含依赖 DLL)
|
||||
└── osslsigncode.exe
|
||||
```
|
||||
|
||||
> `certs/` 与 `tools/` 已在 `go/.gitignore` 中排除,**不会**被提交到版本库,也不会进入发布包。
|
||||
|
||||
### 工具获取(首次安装 / tools/ 被清理后重装)
|
||||
|
||||
`tools/osslsigncode/` 是便携版,不随版本库分发。在 Git Bash 中执行:
|
||||
|
||||
```bash
|
||||
cd go
|
||||
mkdir -p tools && cd tools
|
||||
|
||||
curl -sL -o osslsigncode.zip \
|
||||
https://github.com/mtrojnar/osslsigncode/releases/download/2.14/osslsigncode-2.14-windows-x64-mingw.zip
|
||||
|
||||
unzip -o osslsigncode.zip
|
||||
|
||||
# zip 解压后 exe 在 bin/ 子目录,移动到 sign.bat 引用的布局
|
||||
mkdir -p osslsigncode
|
||||
mv -f bin/* osslsigncode/
|
||||
rm -rf bin share osslsigncode.zip
|
||||
|
||||
# 验证
|
||||
./osslsigncode/osslsigncode.exe --help | head -3
|
||||
```
|
||||
|
||||
> ⚠️ zip 内含 `bin/osslsigncode.exe` + 依赖 DLL(`libcrypto-3-x64.dll`、`libssl-3-x64.dll`、`zlib1.dll`),必须与 exe 同目录,缺 DLL 会运行失败。
|
||||
|
||||
---
|
||||
|
||||
## 三、签发自签名代码签名证书(首次一次)
|
||||
|
||||
> 前置:Git Bash(自带 OpenSSL ≥ 3.1)。以下命令在 Git Bash 中执行。
|
||||
> ⚠️ **MSYS 路径转换坑**:`-subj` 的 `/C=CN/...` 会被 Git Bash 误判为 POSIX 路径,
|
||||
> 必须加 `MSYS_NO_PATHCONV=1` 前缀,否则报 `subject name is expected to be in the format...`。
|
||||
|
||||
```bash
|
||||
cd go
|
||||
mkdir -p certs
|
||||
|
||||
MSYS_NO_PATHCONV=1 openssl req -x509 -newkey rsa:2048 -sha256 -nodes \
|
||||
-keyout certs/codesign.key \
|
||||
-out certs/codesign.crt \
|
||||
-days 3650 \
|
||||
-subj "/C=CN/ST=Sichuan/L=Chengdu/O=Excel Keyword Search Tool/OU=Release/CN=Excel Keyword Search Tool" \
|
||||
-addext "keyUsage=digitalSignature, nonRepudiation" \
|
||||
-addext "extendedKeyUsage=codeSigning" \
|
||||
-addext "basicConstraints=critical,CA:FALSE"
|
||||
```
|
||||
|
||||
参数说明:
|
||||
- `-x509`:直接自签(不经过 CA),`-nodes`:私钥不加密(本地文件使用,配合 `-pass` 保护 pfx)
|
||||
- `-addext extendedKeyUsage=codeSigning`:声明**代码签名**用途(必填,杀软/系统校验此项)
|
||||
- `-basicConstraints=CA:FALSE`:明确非 CA,防被滥用
|
||||
- `-days 3650`:10 年有效期(正式发布建议 ≥ 1 年)
|
||||
|
||||
### 导出 PFX(签名工具实际使用)
|
||||
|
||||
```bash
|
||||
openssl pkcs12 -export \
|
||||
-out certs/codesign.pfx \
|
||||
-inkey certs/codesign.key \
|
||||
-in certs/codesign.crt \
|
||||
-passout pass:ExcelSearch2026 \
|
||||
-name "ExcelKeywordSearchRelease"
|
||||
```
|
||||
|
||||
> `pass:ExcelSearch2026` 是**默认密码**(脚本内置)。正式环境请更换,并通过 `SIGN_PASSWORD` 环境变量注入(见下)。
|
||||
|
||||
### 验证证书
|
||||
|
||||
```bash
|
||||
openssl x509 -in certs/codesign.crt -noout -subject -issuer -dates -text | grep -A3 "Extended Key Usage"
|
||||
# 应输出:Code Signing
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 四、签名可执行文件
|
||||
|
||||
### 方式一:一键脚本 `sign.bat`(推荐)
|
||||
|
||||
在 `go/` 目录下执行(cmd 或双击):
|
||||
|
||||
```bat
|
||||
sign.bat
|
||||
```
|
||||
|
||||
- 自动扫描 `bin\*.exe`,逐个签名 + 时间戳后**原地覆盖**。
|
||||
- 输出:`[sign] SIGNED : excel-search-desktop.exe` 等。
|
||||
- 指定密码:
|
||||
|
||||
```bat
|
||||
set SIGN_PASSWORD=你的强密码
|
||||
sign.bat
|
||||
```
|
||||
|
||||
### 方式二:集成到 `build.bat`(发布流程)
|
||||
|
||||
`build.bat` 已内置可选签名步骤,构建后自动签名:
|
||||
|
||||
```bat
|
||||
set VERSION=v1.2.3
|
||||
set SIGN=1
|
||||
build.bat
|
||||
```
|
||||
|
||||
构建三个 exe → 自动调用 `sign.bat` 全部签名 + 时间戳。
|
||||
|
||||
### 方式三:手动调用 osslsigncode(Git Bash)
|
||||
|
||||
```bash
|
||||
./tools/osslsigncode/osslsigncode.exe sign \
|
||||
-pkcs12 certs/codesign.pfx \
|
||||
-pass "ExcelSearch2026" \
|
||||
-n "Excel Keyword Search Tool" \
|
||||
-t http://timestamp.digicert.com \
|
||||
-in bin/excel-searcher.exe \
|
||||
-out bin/excel-searcher.signed.exe
|
||||
mv -f bin/excel-searcher.signed.exe bin/excel-searcher.exe
|
||||
```
|
||||
|
||||
> osslsigncode **不允许输入输出同一文件**,必须先生成临时文件再覆盖。
|
||||
|
||||
---
|
||||
|
||||
## 五、验证签名
|
||||
|
||||
### Git Bash(osslsigncode)
|
||||
|
||||
```bash
|
||||
./tools/osslsigncode/osslsigncode.exe verify bin/excel-searcher.exe
|
||||
# 期望:Message digest 一致、Signer's certificate 正确、含时间戳信息
|
||||
```
|
||||
|
||||
### PowerShell(系统级,最权威)
|
||||
|
||||
```powershell
|
||||
Get-AuthenticodeSignature .\bin\excel-searcher.exe
|
||||
# Status: Valid
|
||||
# SignerCertificate: CN=Excel Keyword Search Tool, ...
|
||||
# TimeStamperCertificate: CN=DigiCert Timestamp Responder, ...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 六、时间戳说明
|
||||
|
||||
签名时使用 `-t http://timestamp.digicert.com`(RFC 3161 时间戳服务器):
|
||||
|
||||
- **作用**:记录签名发生的准确时刻,即使未来证书过期,**历史签名依然有效**。
|
||||
- **必须加**:不加时间戳的签名会在证书到期后失效。
|
||||
- 备选时间戳服务器:`http://timestamp.sectigo.com`、`http://timestamp.apple.com`。
|
||||
|
||||
---
|
||||
|
||||
## 七、升级到公共证书(彻底消除误报)
|
||||
|
||||
自签名证书只解决"结构误报",若要杀软完全信任并显示有效签名:
|
||||
|
||||
1. 向 **Sectigo / DigiCert / 阿里云 / 腾讯云** 等购买 **OV/EV 代码签名证书**(EV 更优,需硬件 Key,签名前插 U 盾)。
|
||||
2. 拿到 `.pfx` 或证书+私钥后,替换 `certs/codesign.pfx`。
|
||||
3. 其余流程完全一致(`sign.bat` / `build.bat` / 验证方式不变)。
|
||||
|
||||
---
|
||||
|
||||
## 八、安全警示
|
||||
|
||||
- `codesign.key` 与 `codesign.pfx` 是**私钥材料**,一旦泄露,他人可冒名签名恶意程序。
|
||||
- **绝不要**提交进 git、发送给他人或放入发布包。
|
||||
- 建议:
|
||||
- `certs/` 目录仅保留在受控构建机。
|
||||
- 密码定期更换(通过 `SIGN_PASSWORD` 注入,勿写死在文档/脚本明文)。
|
||||
- 发布包只包含**签名后的 exe**,不含任何 `certs/`、`tools/` 内容。
|
||||
|
||||
---
|
||||
|
||||
## 九、常见问题
|
||||
|
||||
**Q:签名后 Symantec 仍然拦截?**
|
||||
- 自签名证书不被 Symantec 信任,部分机器仍可能报"未知发布者"。属预期;误报率已大幅下降。
|
||||
- 彻底解决走「七、升级到公共证书」,并向 Symantec 提交白名单申诉:
|
||||
<https://symantec.brightcloud.com/tools/submiturl>
|
||||
|
||||
**Q:`subject name is expected to be in the format...`?**
|
||||
Git Bash 把 `-subj` 的 `/C=CN` 当路径转换了。加 `MSYS_NO_PATHCONV=1` 前缀重试。
|
||||
|
||||
**Q:`Unable to load provider: legacy` 警告?**
|
||||
osslsigncode 内置 OpenSSL 的提示,不影响 SHA256 签名结果,可忽略。
|
||||
|
||||
**Q:报 `Failed to add store lookup file`?**
|
||||
验证命令的证书链查找提示,只要 `Message digest` 一致、`Signer's certificate` 正确即为签名有效,可忽略。
|
||||
@@ -38,6 +38,19 @@ go build -trimpath -ldflags "-s -w -H=windowsgui -X main.version=%VERSION%" -o b
|
||||
go build -trimpath -ldflags "-s -w -H=windowsgui -X main.version=%VERSION%" -o bin\excel-search-webui.exe .\cmd\webui || goto failed
|
||||
go build -trimpath -ldflags "-s -w -X main.version=%VERSION%" -o bin\excel-searcher.exe .\cmd\searcher || goto failed
|
||||
|
||||
REM ---- Optional code signing (release builds) ----
|
||||
REM Enable with: set SIGN=1 && build.bat
|
||||
if /i "%SIGN%"=="1" (
|
||||
echo.
|
||||
echo [build] Signing artifacts with code signing certificate ...
|
||||
call sign.bat
|
||||
if errorlevel 1 (
|
||||
echo [build] Signing failed.
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
)
|
||||
|
||||
echo.
|
||||
echo [build] Build succeeded (version %VERSION%), artifacts in bin\:
|
||||
dir /b bin
|
||||
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
@echo off
|
||||
REM ============================================================
|
||||
REM Excel Keyword Search Tool - code signing script
|
||||
REM Signs every exe in bin\ with Authenticode + RFC3161 timestamp
|
||||
REM (timestamp keeps signature valid after cert expiry).
|
||||
REM
|
||||
REM Usage:
|
||||
REM sign.bat sign bin\*.exe with default pfx password
|
||||
REM set SIGN_PASSWORD=xxx && sign.bat use custom pfx password
|
||||
REM
|
||||
REM Prerequisites:
|
||||
REM certs\codesign.pfx must exist (private key material, gitignored)
|
||||
REM tools\osslsigncode\ portable build must be present
|
||||
REM NOTE: keep this file pure ASCII to avoid cmd codepage garbling.
|
||||
REM ============================================================
|
||||
setlocal enabledelayedexpansion
|
||||
|
||||
set "ROOT=%~dp0"
|
||||
set "PFX=%ROOT%certs\codesign.pfx"
|
||||
set "SIGNEXE=%ROOT%tools\osslsigncode\osslsigncode.exe"
|
||||
if "%SIGN_PASSWORD%"=="" set "SIGN_PASSWORD=ExcelSearch2026"
|
||||
set "TS_SERVER=http://timestamp.digicert.com"
|
||||
set "APPNAME=Excel Keyword Search Tool"
|
||||
|
||||
if not exist "%PFX%" (
|
||||
echo [sign] ERROR: certificate not found at %PFX%
|
||||
exit /b 1
|
||||
)
|
||||
if not exist "%SIGNEXE%" (
|
||||
echo [sign] ERROR: osslsigncode not found at %SIGNEXE%
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
set "COUNT=0"
|
||||
set "FAILED=0"
|
||||
for %%f in ("%ROOT%bin\*.exe") do (
|
||||
if exist "%%f" (
|
||||
"%SIGNEXE%" sign -pkcs12 "%PFX%" -pass "%SIGN_PASSWORD%" -n "%APPNAME%" -t "%TS_SERVER%" -in "%%f" -out "%%~dpnf.signed.exe" >nul 2>&1
|
||||
if errorlevel 1 (
|
||||
echo [sign] FAILED : %%~nxf
|
||||
set /a FAILED+=1
|
||||
) else (
|
||||
move /y "%%~dpnf.signed.exe" "%%f" >nul 2>&1
|
||||
echo [sign] SIGNED : %%~nxf
|
||||
set /a COUNT+=1
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
echo.
|
||||
if %FAILED% gtr 0 (
|
||||
echo [sign] Done: %COUNT% signed, %FAILED% failed.
|
||||
exit /b 1
|
||||
)
|
||||
echo [sign] Done: %COUNT% executable(s) signed and timestamped.
|
||||
exit /b 0␍
|
||||
Reference in new issue
Block a user