- 应用安全
- 开发工具
【免费下载链接】gopass
The slightly more awesome standard unix password manager for teams
本篇技术指南以 gopass 的generate命令为核心,讲解如何生成新密码并写入密码库、为既有条目重新生成密码、向 YAML 键写入新密码,以及 cryptic / xkcd / memorable / external 四种密码生成器的选择与配置。通过阅读本文,你将掌握generate的完整参数语义、退出码约定、相关配置项,以及.pass-template模板预填充机制,能够独立完成从"生成密码"到"安全存储"的实战闭环。
命令概览与定位
generate命令用于生成一个新密码,并将其写入密码库(password store)。它是 gopass 日常使用中频率最高的写操作之一:新建账号时用它生成初始密码,轮换凭证时用它为既有条目重新生成密码。
注意:如果你只想生成一个密码、而不希望把它存进密码库,应当使用
pwgen命令,其用法详见 pwgen 命令文档。
从源码看,该命令定义于 internal/action/commands.go#L538-L619,其参数格式为[secret [key [length]|length]],默认行为是"将新密码替换既有条目的第一行(Password 字段),或新建一个条目",核心实现位于 internal/action/generate.go 的Generate方法。
语法(Synopsis)
gopass generate entry [length] gopass generate entry key [length]entry:目标秘密条目的名称,可含路径,例如websites/example.com/john.doe。key:可选,指定要向该条目中的哪个 YAML 键写入新密码。length:可选,生成密码的长度;对于 xkcd 生成器而言,它表示单词数量而非字符数。
参数解析逻辑见 internal/action/generate.go#L101-L115 的keyAndLength:当只提供一个非纯数字参数时,它被当作key;当提供一个纯数字参数时,它被当作length;提供两个参数时,分别对应key与length。
四种操作模式(Modes of operation)
- 新建条目并生成密码:
gopass generate entry [chars],设置新条目的Password字段,例如注册一个新登录账号。 - 为既有条目重新生成密码:
gopass generate entry [chars](条目已存在),生成新密码并替换其Password字段。 - 为既有条目的新键生成密码:
gopass generate entry key [chars],例如为某个已存秘密新增一个api-key字段并写入随机密码。 - 为既有条目的既有键重新生成密码:
gopass generate entry key [chars](该键已存在),重写该键的值。
需要说明的是,当key未指定且条目已存在时,Generate会先向用户确认是否覆盖(除非使用--force),见 internal/action/generate.go#L64-L69;用户拒绝时返回退出码 3。
参数(Flags)
下表为generate的完整参数列表,语义与 internal/action/commands.go#L547-L617 中的定义一致:
| Flag | 别名 | 说明 |
|---|---|---|
--clip | -c | 把生成的密码复制到剪贴板。默认取配置generate.autoclip的值。 |
--print | -p | 把生成的密码打印到终端。默认false。 |
--force | -f | 强制覆盖已存在的条目(跳过确认)。 |
--edit | -e | 生成密码后用$EDITOR打开该条目以便继续编辑补充。 |
--generator | -g | 选择密码生成器:cryptic、memorable、xkcd、external。默认cryptic。 |
--symbols | -s | 在生成的密码中包含符号字符。默认false。 |
--strict | 确保每个请求的字符类别确实被包含。不带此选项时,所有类别"可以但不保证"被包含。默认false。 | |
--xkcd-sep | --sep、--xkcdsep | 多词生成器的单词分隔符。 |
--xkcd-lang | --lang、--xkcdlang | 词表语言,目前支持en(默认)与de。 |
--xkcd-capitalize | --xkcdcapitalize | 使用xkcd生成器时每个单词首字母大写,等价于配置pwgen.xkcd-capitalize = true。 |
--xkcd-numbers | --xkcdnumbers | 使用xkcd生成器时在每个单词后追加随机数字,等价于配置pwgen.xkcd-numbers = true。 |
--force-regen | 强制完全重新生成(包括重新评估模板),会整体覆盖整个条目,而非仅替换密码字段。 | |
--commit-message | -m | 自定义本次写入的 Git 提交信息。 |
--interactive-commit | -i | 打开编辑器交互式输入提交信息。 |
其中--force-regen、--commit-message、--interactive-commit在原命令文档中未列出,但确实存在于 internal/action/commands.go#L582-L617 的命令定义中,属于该命令的完整参数面。
四种密码生成器(Password Generators)
通过--generator(或配置generate.generator)选择生成器:
| 生成器 | 说明 |
|---|---|
cryptic | 默认生成器,产出与多数网站兼容的"难记型"随机密码。可用--symbols与--strict满足特定站点要求;部分站点会自动套用其密码规则(见下文"站点规则自动检测")。长度参数表示字符数。 |
xkcd | 使用 XKCD#936 风格的密码(多词组合)。可用--xkcd-lang与--xkcd-sep调整行为。长度参数表示单词数量。 |
memorable | 生成"可记忆型"密码。长度参数表示最小字符数——注意若最小长度方案未满足全部规则要求,输出可能更长。 |
external | 调用$GOPASS_EXTERNAL_PWGEN指定的外部生成程序。 |
cryptic 生成器底层原理
cryptic 生成器的实现位于 pkg/pwgen/cryptic.go。其字符集由 pkg/pwgen/pwgen.go#L17-L35 定义的四类字符组成:
- 数字
Digits = "0123456789" - 大写字母
Upper = "A-Z" - 小写字母
Lower = "a-z" - 符号
Syms = "!\"#$%&'()*+,-./:;<=>?@[\\]^_\{|}~"`
NewCryptic(length, symbols)默认长度为 16(若传入 < 1 则回退到 16),启用符号时把Syms追加进字符集。生成时最多重试 64 轮(MaxTries),每轮随机抽取字符,直到满足所有注册的校验器(validators)为止;超过重试上限则返回空串。
--strict模式对应GeneratePasswordWithAllClasses(pkg/pwgen/pwgen.go#L61-L74),它注册一个"必须包含全部启用字符类别"的校验器,确保数字、大小写字母(以及启用的符号)每种至少出现一个——这正是--strict与默认"可能但不保证包含"的关键差异。
xkcd 生成器底层原理
xkcd 生成器在 internal/action/generate.go#L307-L353 的generatePasswordXKCD中编排:命令行参数优先,其次读取pwgen.xkcd-*系列配置,最后(当长度未给定且未配置pwgen.xkcd-len)交互式询问"用多少个单词组合"。实际词表抽样由 pkg/pwgen/xkcdgen/pwgen.go 的RandomLengthDelim完成,支持en/de两种语言词表。
memorable 生成器底层原理
GenerateMemorablePassword(minLength, symbols, capitals)位于 pkg/pwgen/memorable.go:循环从内置词表抽取单词,每个单词后追加一个随机数字(可选再追加一个符号),直到总长度达到最小要求。因为按"整词 + 数字"拼接,最终长度通常大于请求的最小值;启用大写时还会随机对部分单词做首字母大写。
external 生成器底层原理
GenerateExternal(pwlen)位于 pkg/pwgen/external.go:读取环境变量GOPASS_EXTERNAL_PWGEN(可为带参数的命令行),用 shellquote 拆分后执行,并把请求长度作为最后一个参数追加,最后取程序标准输出的首行(去空白)作为密码。未设置该环境变量时返回no external generator错误。
站点规则自动检测(Password Rules)
generate的一个贴心特性是根据秘密名称自动检测目标站点的密码规则。hasPwRuleForSecret(internal/action/generate.go#L164-L178)会从秘密路径的末端开始逐级向上提取"看起来像域名"的路径段,并在pwrules规则库(见 pkg/pwgen/pwrules)中查找对应规则;命中后(且未用--force绕过)调用generatePasswordForRule(internal/action/generate.go#L265-L305):
- 校验用户给的长度是否落在规则的
Minlen~Maxlen区间内,不满足则提示"请输入 (min: N, max: N)"并递归追问,直到合法; - 用
NewCrypticForDomain(pkg/pwgen/cryptic.go#L54-L114)构造生成器:按规则的Required/Allowed字符类别裁剪字符集、追加"必须包含某类字符""最多连续 N 个同类字符"等校验器,并保证密码长度至少覆盖规则要求的类别数; - 同时,若该域名配置了修改密码 URL,新条目会自动写入
password-change-url字段(见hasChangeURL,internal/action/generate.go#L414-L423)。
相关逻辑有测试覆盖,例如 internal/action/generate_test.go#L383-L450 的TestHasPwRuleForSecret验证了websites/apple.com/gopass这类路径能正确命中apple.com的规则。
密码长度:交互式询问与环境变量
未在命令行给定长度时,generate通过getPwLengthFromEnvOrAskUser(internal/action/generate.go#L243-L263)决定长度:若环境变量GOPASS_PW_DEFAULT_LENGTH已设置为合法正整数,则直接采用(不再询问);否则以默认长度为初值交互式询问"How long should the password be?"。非法值(如0、负数、非数字)会被忽略并回退到默认长度(24),该行为在 internal/action/generate_test.go#L351-L381 的TestDefaultLengthFromEnv中逐一验证。xkcd 生成器未给长度时的默认单词数为 4(配置pwgen.xkcd-len)。
输出与剪贴板行为
生成密码后的展示逻辑集中在generateCopyOrPrint(internal/action/generate.go#L117-L162),规则如下:
- 显式
-c,或配置generate.autoclip = true且输出未被重定向(即标准输出仍是终端)时,把密码复制到剪贴板,剪贴板保留时长由core.cliptimeout决定; - 复制成功后若开了 autoclip 且未显式
-p,输出一行 "Copied to clipboard"; - 未复制且未显式
-p时,默认不打印密码,仅提示 "Not printing secrets by default. Use 'gopass show ' to display the password."——这是 gopass 的安全默认; - 显式
-p时打印密码,但若show.safecontent为真且-p被显式置为false,打印仍会被抑制。
因此,默认情况下生成后你不会在屏幕上看到密码本身,只能通过gopass show查看,或依赖剪贴板/显式-p。
退出码(Exit codes)
generate使用结构化数字退出码,方便脚本判别失败原因(数值稳定,不会在版本间重排)。generate相关的退出码如下:
| 码 | 含义 |
|---|---|
| 0 | 密码生成并成功存储 |
| 2 | 长度参数不是合法的正整数 |
| 3 | 用户拒绝覆盖既有秘密 |
| 9 | 未提供秘密名称 |
| 12 | 生成的秘密无法加密并保存 |
| 18 | 生成的密码无法复制到剪贴板 |
完整退出码表及所有命令的逐命令摘要见 docs/exit-codes.md,也可以在终端随时执行gopass --exit-codes打印。脚本示例:
gopass generate websites/example.com 32 case $? in 0) echo "OK" ;; 2) echo "Bad length argument" ;; 3) echo "User aborted" ;; 9) echo "No name provided" ;; 12) echo "Encrypt/save failed" ;; 18) echo "Clipboard copy failed" ;; *) echo "Unexpected error ($?)" ;; esac相关配置项(Relevant configuration options)
结合 docs/config.md 的配置总表,generate涉及的配置如下:
| 配置项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
generate.autoclip | bool | false | 仅对generate生效。为真时生成后自动把密码复制到剪贴板——除非显式指定--clip=false覆盖。 |
generate.generator | string | 空 | 默认密码生成器,可取xkcd、memorable、external或留空(即 cryptic)。 |
generate.symbols | bool | false | 生成的密码是否包含符号。 |
generate.strict | bool | false | 是否默认启用严格模式(保证每个字符类别至少出现一次)。 |
pwgen.xkcd-sep | string | (空格) | xkcd 密码的单词分隔符。 |
pwgen.xkcd-lang | string | en | xkcd 词表语言。 |
pwgen.xkcd-capitalize | bool | false | 每个单词首字母大写。注意:分隔符为空时默认改为大写。 |
pwgen.xkcd-numbers | bool | false | 每个单词后追加随机数字。 |
pwgen.xkcd-len | int | 4 | xkcd 密码的默认单词数。 |
show.safecontent | bool | false | 为真时抑制打印密码(除非-p);密码也不会被复制,除非-c或generate.autoclip开启。 |
core.cliptimeout | int | 秒数 | 剪贴板内容自动清除的超时时间。 |
查看与修改方法:
gopass config generate.autoclip # 查看 gopass config generate.autoclip true # 设置配置读写命令详见 config 命令文档。源码中generate.autoclip、generate.generator、generate.symbols、generate.strict的实际读取位置分别见 internal/action/generate.go#L130、#L188-L191、#L197-L204、#L534-L543。
模板(Templates):用.pass-template预填充新条目
创建新条目时,gopass 会沿着秘密路径逐级向上查找名为.pass-template的文件(最具体的模板优先):先看条目所在目录,再逐级上溯到根。逻辑实现于 internal/store/leaf/templates.go#L23-L48 的LookupTemplate,模板文件常量TemplateFile = ".pass-template"。
一旦找到模板,gopass 会用模板内容预填充新生成的秘密(见 internal/action/generate.go#L395-L402 的模板渲染分支),之后你还可以结合--edit打开编辑器补齐其余字段。
实战示例
假设目录结构如下:
password-store/ └── websites/ ├── .pass-template └── example.com/websites/.pass-template内容:
username: john.doe url: https://example.com note: managed by gopass执行gopass generate websites/example.com/john.doe 24后,新条目会以该模板为基础生成:密码写入Password字段(第一行),username、url、note等键自动填充。这样可以在团队内为同类账号统一字段结构,配合gopass edit做二次完善。模板的全局管理命令见 templates 命令文档。
典型使用流程
注册新账号
gopass generate websites/example.com/john.doe 24生成 24 字符 cryptic 密码并新建条目;默认不打印密码,可加
-c复制到剪贴板。按站点规则生成:路径末端包含已知域名时自动套用该站规则:
gopass generate websites/apple.com/john.doegopass 会自动选择符合 apple.com 规则的字符集与长度范围(可看到 "Using password rules for apple.com ..." 提示)。
为已有条目的 YAML 键生成:
gopass generate websites/example.com/john.doe api-key 32xkcd 风格密码(多词短语):
gopass generate --generator xkcd websites/example.com/john.doe 4 gopass generate --generator xkcd --xkcd-sep - --xkcd-capitalize --xkcd-numbers websites/example.com/john.doe 4生成后立即编辑补充:
gopass generate --edit --force websites/example.com/john.doe 32强制覆盖并自定义提交信息(适合脚本化轮换凭证):
gopass generate --force -m "rotate api key" websites/example.com/john.doe api-key 48只生成不存储:使用 pwgen 命令:
gopass pwgen 24 5
测试与验证
generate的端到端行为有完整测试覆盖:internal/action/generate_test.go 验证了新建条目、重复生成、--force覆盖、--edit联动、--symbols/--xkcd各分支、autoclip 在输出重定向与否下的不同提示,以及GOPASS_PW_DEFAULT_LENGTH=42时生成 42 字符密码、非法值回退默认长度等场景;TestKeyAndLength(internal/action/generate_test.go#L220-L264)则直接验证了key/length位置参数的解析规则。若想深入调试,可参考仓库中的测试辅助包 tests/gptest。
小结
generate是 gopass 中"造密入库"的一站式入口:它把随机密码生成、站点规则适配、剪贴板/终端输出策略、YAML 键写入、模板预填充和 Git 提交整合为一条命令,配合稳定的退出码非常适合脚本化与团队工作流。理解--generator、--strict、--symbols与generate.autoclip、show.safecontent等配置的相互作用,是安全、高效使用 gopass 的关键一步。
- 应用安全
- 开发工具
【免费下载链接】gopass
The slightly more awesome standard unix password manager for teams
相关推荐
oclif generate 命令完全指南:从零生成 CLI、命令与 Hook
oclif generate 命令完全指南:从零生成 CLI、命令与 Hook 本指南围绕 oclif 仓库中的 generate 系列命令展开,完整讲解 oc
开发工具.NET 运行时 Type Forwarding 全面解析:从元数据 ExportedType 到 Profiling API 的实践指南
.NET 运行时 Type Forwarding 全面解析:从元数据 ExportedType 到 Profiling API 的实践指南 本文以 .NET C
应用安全开发工具chezmoi 集成 gopass:用 gopass 模板函数在 dotfiles 中安全注入密码与密钥
chezmoi 集成 gopass:用 gopass 模板函数在 dotfiles 中安全注入密码与密钥 chezmoi 内置了对 gopass(基于 GPG
开发工具CLI配置管理
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考