scan4all 项目中的 minisign:文件签名与验签的极简安全方案全解析
2026/9/17 20:17:05 网站建设 项目流程

scan4all 项目中的 minisign:文件签名与验签的极简安全方案全解析

【免费下载链接】scan4allOfficial repository vuls Scan: 15000+PoCs; 23 kinds of application password crack; 7000+Web fingerprints; 146 protocols and 90000+ rules Port scanning; Fuzz, HW, awesome BugBounty( ͡° ͜ʖ ͡°)...项目地址: https://gitcode.com/GitHub_Trending/sca/scan4all

导读

minisign 是一个"极简到极致"的文件签名与验签工具,它用一条命令完成密钥对生成、一条命令完成签名、一条命令完成验签,却内置了 Ed25519 数字签名、BLAKE2b 哈希与 scrypt 口令派生等完整的现代密码学能力。在 scan4all 项目中,aead.dev/minisignv0.2.0 作为间接依赖随 Go module 一起被 vendoring 进仓库(见 go.mod 与 vendor/modules.txt),其完整实现代码就位于 vendor/aead.dev/minisign/。读完本文,你将掌握 minisign 命令行工具的完整用法(生成密钥、签名、验签、恢复公钥)、全部 13 个命令行参数的语义,以及它的 Go 语言库级 API 与底层密码学原理,可以直接用于构建自己的软件分发签名校验流程。

一、minisign 是什么:Go 实现的极简签名工具

minisign 由 Andreas Auernhammer 用 Go 语言实现,是 Frank Denis 原始 C 实现的移植版本。它被设计为"dead simple"——只专注做三件事:

  1. 生成(Generate):创建一对公私钥;
  2. 签名(Sign):用私钥为文件生成签名文件;
  3. 验证(Verify):用公钥验证文件的签名是否有效。

它在设计上的关键决策是密钥对默认受口令保护:生成的私钥不是裸的 Ed25519 密钥,而是用用户口令经 scrypt 密钥派生后加密存储的密文,任何拿到私钥文件的人都无法直接使用,必须输入正确的口令。这种"私钥加密落地"的设计让 minisign 特别适合个人开发者签名发布软件包、脚本或配置文件的使用场景。

二、快速上手:三个命令完成全流程

minisign 的 CLI 使用体验非常直观,README 给出了完整的三步走示例(密钥生成 → 签名 → 验签),下面逐一展开。

第一步:生成密钥对(-G

$ minisign -G Please enter a password to protect the secret key. Enter Password: Enter Password (one more time): Deriving a key from the password in order to encrypt the secret key... done The secret key was saved as ~/.minisign/minisign.key - Keep it secret! The public key was published as minisign.pub - That one can be public. Files signed using this key pair can be verified with the following command: minisign -Vm <file> -P RWSYKA736yqh+JrZ7cRDdWgck/WKtwW9ATBFmk8pQ1lHeUKXtV6uJ7Fu

-G模式会交互式要求输入两遍口令来保护私钥,然后用 scrypt 从口令派生密钥并加密私钥。命令结束时:

  • 私钥保存到~/.minisign/minisign.key,必须保密;
  • 公钥保存到当前目录的minisign.pub,可以公开分发;
  • 终端会直接打印出"用该密钥对验签"的标准命令,公钥以 Base64 字符串形式内嵌其中(-P参数),方便你拷贝到任何机器上立即验签,无需携带公钥文件。

第二步:签名文件(-S

$ minisign -Sm message.txt Enter password: Deriving a key from the password in order to decrypt the secret key... done

-S表示签名(Sign),-m message.txt指定待签名文件。由于私钥是加密存储的,这一步需要输入生成密钥对时设置的口令,程序会解密私钥、计算文件签名并写出默认的签名文件message.txt.minisig

第三步:验证签名(-V

$ minisign -Vm message.txt Signature and comment signature verified Trusted comment: timestamp:1614718943 filename:message.txt

-V表示验签(Verify),-m message.txt指定待验证文件。验证通过后输出两行信息:

  • 第一行确认文件签名comment 签名双双验证成功;
  • 第二行展示签名中携带的 trusted comment——这里可以看到 minisign 默认在签名里自动嵌入的时间戳与文件名,用于审计"这个签名是什么时候、针对哪个文件生成的"。

如果文件在签名后被篡改过,验证会失败并给出明确报错。

三、命令行完整参考:四种模式与全部参数

README 给出了 minisign CLI 的完整语法,整理如下。

语法总览

Usage: minisign -G [-p <pubKey>] [-s <secKey>] minisign -S [-x <signature>] [-s <secKey>] [-c <comment>] [-t <comment>] -m <file>... minisign -V [-H] [-x <signature>] [-p <pubKey> | -P <pubKey>] [-o] [-q | -Q ] -m <file> minisign -R [-s <secKey>] [-p <pubKey>]

四种操作模式

模式参数说明
生成-G生成一对新的公钥/私钥
签名-S使用私钥为文件签名
验签-V使用公钥验证文件签名
恢复-R从私钥重新生成公钥文件

全部参数详解

参数作用默认值
-m <file>要签名或验证的文件必填
-o配合-V使用,验证通过后将文件内容输出到标准输出关闭
-H配合-V使用,要求对"预哈希后的文件"进行验签关闭
-p <pubKey>指定公钥文件路径./minisign.pub
-P <pubKey>直接以 Base64 字符串形式传入公钥
-s <secKey>指定私钥文件路径$HOME/.minisign/minisign.key
-x <signature>指定签名文件路径<file>.minisig
-c <comment>添加一行非受信注释
-t <comment>添加一行受信注释时间戳+文件名
-q安静模式,抑制输出关闭
-Q极简安静模式,配合-V仅打印受信注释关闭
-f配合-G-R,覆盖已存在的公钥/私钥文件关闭
-v打印版本信息关闭

其中两个细节值得特别说明:

-p-P是互斥的-p指定公钥文件路径,-P直接内嵌公钥的 Base64 文本。后者正是上面"生成密钥对"输出中那条验签命令所用的形式,适合在没有公钥文件的场景下快速验签。

-c-t的信任语义截然不同(对应源码中的UntrustedCommentTrustedComment,见 signature.go):

  • -t指定的受信注释会被签名,验签时若被篡改则验证失败,可以安全信任;
  • -c指定的非受信注释不参与签名,任何人可以改它而不破坏签名,绝不能作为信任依据。

四、安装:预编译二进制与源码构建两种方式

README 提供了两种安装路径。

方式一:使用预编译二进制

minisign 为 Windows、Linux、macOS 三大平台发布预编译产物,官方 README 中以 v0.1.2 为例列出的构建矩阵如下:

操作系统架构发行包
Linuxamd64minisign-linux-amd64.tar.gz
Linuxarm64minisign-linux-arm64.tar.gz
macOSarm64minisign-darwin-arm64.tar.gz
macOSamd64minisign-darwin-amd64.tar.gz
Windowsamd64minisign-windows-amd64.zip

下载对应平台的压缩包解压后即可直接使用,无需任何运行时依赖。注意:这里列的发行版号以官方 release 页面的最新 tag 为准,本文引用的仓库中 vendoring 的版本为 v0.2.0(见 go.sum)。

方式二:从源码构建(Go 1.16+)

如果你的系统已安装 Go 1.16 及以上版本,可以一条命令从源码构建:

git clone https://aead.dev/minisign && cd minisign go build -o . aead.dev/minisign/cmd/minisign

构建产物就是当前目录下的minisign可执行文件。这与 scan4all 仓库中对该模块的 vendoring 方式一致——aead.dev/minisign以独立 Go module 的身份被引入并固化在 vendor/ 目录下,构建时不需要联网拉取。

五、作为 Go 库使用:签名验签的最小代码

除了命令行工具,minisign 还暴露了完整的 Go 语言库 API,只需要一行 import:

import "aead.dev/minisign"

README 给出了一个完整的库级示例:生成密钥对 → 签名 → 验签的闭环。

package main import ( "crypto/rand" "log" "aead.dev/minisign" ) func main() { var message = []byte("Hello World!") public, private, err := minisign.GenerateKey(rand.Reader) if err != nil { log.Fatalln(err) } signature := minisign.Sign(private, message) if !minisign.Verify(public, message, signature) { log.Fatalln("signature verification failed") } log.Println(string(message)) }

这个示例覆盖了库的四个核心 API:

API签名作用
GenerateKey(random io.Reader)func GenerateKey(random io.Reader) (PublicKey, PrivateKey, error)用熵源生成公私钥对,randomnil时使用crypto/rand.Reader(见 minisign.go)
Sign(private PrivateKey, message []byte) []bytefunc Sign(privateKey PrivateKey, message []byte) []byte对消息签名,返回可传输的签名文本(含默认注释)
Verify(public PublicKey, message, signature []byte) boolfunc Verify(publicKey PublicKey, message, signature []byte) bool验证签名,返回布尔结果
GenerateKey生成的公钥/私钥PublicKey/PrivateKey类型分别实现crypto.PublicKeycrypto.Signer接口

底层库还提供了更多进阶 API,例如:

  • SignWithComments/Reader.SignWithComments:自定义受信与非受信注释;
  • Reader流式签名验签:边读取边计算哈希,支持对超长文件(无法整体载入内存)做HashEdDSA预哈希签名,也能对同一消息的前缀片段生成快照签名(见 minisign.go);
  • PublicKeyFromFile/PrivateKeyFromFile(password, path)/SignatureFromFile:从文件加载密钥与签名(见 public.go、private.go、signature.go)。

六、底层原理:读懂 minisign 的密码学设计

结合 vendor/aead.dev/minisign/ 下的源码,可以完整还原 minisign 的密码学实现细节。

6.1 签名算法:Ed25519 + BLAKE2b

minisign 的签名算法基于 Ed25519(包注释与EdDSA uint16 = 0x6445常量可见于 minisign.go):

  • EdDSA(0x6445):直接对完整消息签名,用于能整体放入内存的文件;
  • HashEdDSA(0x4445):先对消息做 BLAKE2b-512 哈希再签名,用于无法载入内存的大文件(配合 CLI 的-H参数与库的Reader流式接口)。

验签时对HashEdDSA签名会自动先对消息做blake2b.Sum512再交给 Ed25519 验证(见 minisign.go)。因此两种算法产出的签名在验签端是透明兼容的。

6.2 双签名机制:消息签名 + 注释签名

每次签名实际上会产生两个 Ed25519 签名(见 minisign.go):

  1. msgSignature = Ed25519(私钥, 消息):对消息本体签名;
  2. commentSignature = Ed25519(私钥, msgSignature || trustedComment):对"消息签名 + 受信注释"拼接结果再签名。

由此在验签时得到两层保证:消息未被篡改,且受信注释(如时间戳、文件名)是真实可信的。而非受信注释只是签名文件第一行的纯文本前缀,不参与任何签名计算。

6.3 签名文件格式

签名是纯文本的四行结构,由Signature.String()方法生成(见 signature.go):

untrusted comment: <非受信注释> <Base64(2字节算法 || 8字节KeyID || 64字节消息签名)> trusted comment: <受信注释> <Base64(64字节注释签名)>

解析时(UnmarshalText)严格校验四行结构、算法标识(只允许EdDSA/HashEdDSA)、各段长度以及注释前缀,任何一项不合法都会返回错误(见 signature.go)。

6.4 密钥格式与私钥加密(scrypt + 异或流加密)

公钥的文本格式为一行注释加一行 Base64:2字节算法 || 8字节KeyID || 32字节Ed25519公钥(见 public.go)。其中的 64 位KeyID由公钥本身经 BLAKE2b-256 哈希后取前 8 字节小端序得到(见 minisign.go),用于在验签时快速定位候选公钥。

私钥落地时经过口令加密,格式为固定 158 字节:2字节算法 || 2字节scrypt标识(0x6353) || 2字节blake2b标识(0x3242) || 32字节随机盐 || 8字节scrypt ops || 8字节scrypt mem || 104字节密文(见 private.go)。加密流程(见encryptKey,private.go):

  1. 明文 = 8 字节 KeyID ‖ 64 字节 Ed25519 私钥(共 72 字节);
  2. 计算完整性标签tag = BLAKE2b-256(0x6445 || 明文)
  3. scrypt(口令, 盐, N, r, p)派生 104 字节密钥流;
  4. 密文 = (明文 ‖ tag) ⊕ 密钥流。

解密时反向异或出明文与标签,用常量时间比较(subtle.ConstantTimeCompare)校验标签,防止针对口令的侧信道攻击(见 private.go)。默认的 scrypt 成本参数ops=33554432mem=1073741824对齐 libsodium 的OPS_LIMIT_SENSITIVE/MEM_LIMIT_SENSITIVE,且设有上限(0x2000000ops、0x40000000mem)防止恶意构造的密钥文件拖垮验签端(见 private.go)。

6.5 签名确定性

minisign 的签名是确定性的PrivateKey.Sign不需要也不使用随机源(io.Reader参数被忽略),相同消息 + 相同私钥永远产出相同签名(见 private.go)。这归功于 Ed25519 签名算法本身的确定性设计,便于签名结果的重复比对与审计。

七、在 scan4all 中的定位与延伸阅读

在本仓库中,aead.dev/minisign以 v0.2.0 作为间接依赖出现(go.mod),源码被完整 vendoring 到 vendor/aead.dev/minisign/(包含minisign.goprivate.gopublic.gosignature.go与 LICENSE、README)。这类签名库在安全工具链中的典型用途是:校验外部下发的 PoC 模板、指纹规则或漏洞库更新包是否来自可信发布方、是否在传输中被篡改——这正是 minisign 设计的核心场景。

如果你想进一步实践,可以在 scan4all 的 Go 代码中直接以aead.dev/minisign包为依赖,参考上文第五节的最小示例,把"验签"逻辑接入到项目读取外部规则文件的入口处;日常验证第三方下发的文件签名,则直接使用第三节的 CLI 命令即可。

结语

minisign 的价值在于用最少的命令数封装了完整且现代的密码学栈:Ed25519 提供抗篡改的数字签名,BLAKE2b 提供高速哈希与密钥 ID 派生,scrypt 提供抗暴力破解的口令保护,双签名机制让"受信注释"真正可信。无论是独立命令行使用,还是像 scan4all 这样将其作为 Go 依赖嵌入自己的安全工具链,minisign 都提供了一个简单、可审计、开箱即用的文件签名方案。

参考文件索引

  • 官方文档主体:vendor/aead.dev/minisign/README.md
  • 核心实现(签名/验签/流式接口):vendor/aead.dev/minisign/minisign.go
  • 私钥加密与解密实现:vendor/aead.dev/minisign/private.go
  • 公钥解析与序列化:vendor/aead.dev/minisign/public.go
  • 签名格式定义与解析:vendor/aead.dev/minisign/signature.go
  • 依赖声明:go.mod、go.sum、vendor/modules.txt

【免费下载链接】scan4allOfficial repository vuls Scan: 15000+PoCs; 23 kinds of application password crack; 7000+Web fingerprints; 146 protocols and 90000+ rules Port scanning; Fuzz, HW, awesome BugBounty( ͡° ͜ʖ ͡°)...项目地址: https://gitcode.com/GitHub_Trending/sca/scan4all

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询