- 应用安全
- 开发工具
【免费下载链接】gopass
The slightly more awesome standard unix password manager for teams
gopass cat是 gopass 密码管理器中面向二进制数据流的专用命令:它把 STDIN 上的任意数据流(文本、图片、证书、密钥文件等)Base64 编码后存入密码库,并把库中已编码的条目解码回 STDOUT 输出,实现"管道进、管道出"的存取闭环。读完本文,你将掌握gopass cat的完整语法、三种工作模式、底层存储格式(MIME 风格的元数据 + Base64 载荷)以及它与insert、show等命令的本质区别,能够安全地把非文本敏感文件纳入 gopass 统一管理。
命令概览:为什么需要一个"二进制版 cat"
gopass 的密码库底层以文本形式组织内容,常规的insert命令会把输入解析成"首行密码 + 键值对"结构(详见下文对比)。但当你需要存储图片、SSH 私钥、加密证书、压缩包等二进制数据时,这种解析会破坏原始字节。为此 gopass 提供了cat命令——它的设计定位正是"把密码从 STDIN 管道进来、从 STDOUT 管道出去",并为了兼容二进制数据,在入库前对数据流做编码处理。
官方文档 docs/commands/cat.md 明确指出:
The
catcommand is used to pipe password in and out of STDIN and STDOUT respectively. As it is intended to be used with binary data, it encodes the># 从 STDIN 写入:echo 一段文本,编码后存入 test/new $ echo "test" | gopass cat test/new # 从 STDOUT 读出:解码 test/new 并打印原始内容 $ gopass cat test/new命令只接受一个位置参数
[secret](即目标条目名),例如test/new。如果未提供名称,源码 internal/action/binary.go 会直接返回NoName级别的用法错误:Usage: gopass cat <NAME>。三种工作模式
依据文档,
cat支持三种操作模式:
- 创建新条目:把 STDIN 的数据流编码后写入一个尚不存在的条目;
- 更新已有条目:把 STDIN 的数据流编码后覆盖同名的已有条目;
- 读取条目:把密码库中已编码的数据解码后回显到 STDOUT。
模式由输入来源自动判定:当 STDIN 是管道/重定向(非字符设备)时走"写入"分支,当 STDIN 是交互式终端时走"读取"分支。源码 internal/action/binary.go 用
binstdin.Stat()检查info.Mode()&os.ModeCharDevice == 0来判断是否为管道输入:// if content is piped to stdin, read and save it. if info.Mode()&os.ModeCharDevice == 0 { debug.Log("Reading from STDIN ...") content := &bytes.Buffer{} if written, err := io.Copy(content, binstdin); err != nil { return exit.Error(exit.IO, err, "Failed to copy after %d bytes: %s", written, err) } ... }
io.Copy保证了任意长度的数据流都能被完整读入,测试 internal/action/binary_test.go(TestBinaryCatSizes)专门从 1 KiB 一直循环到bufio.MaxScanTokenSize*2(约 1 MiB 量级)验证"输入与输出逐字节一致"。完整实战示例
官方文档给出了一个从写入、查看存储格式到读出的完整闭环示例:
$ echo "234" | gopass cat test/new $ gopass show -f test/new Secret: test/new content-disposition: attachment; filename="STDIN" content-transfer-encoding: Base64 MjM0Cg== $ gopass cat test/new 234逐段解读:
echo "234" | gopass cat test/new:把字符串234\n编码并写入条目test/new;gopass show -f test/new:强制以原始形式查看存储内容,可以看到条目由两段 MIME 风格的元数据和一段 Base64 载荷构成;MjM0Cg==正是234\n的 Base64 编码;gopass cat test/new:解码MjM0Cg==并在 STDOUT 打印出原始的234。存储格式:Base64 编码与 MIME 元数据
文档说明:cat 从 STDIN 读取二进制流,将其Base64 编码后存入密码库,并附上关于输入来源与所用编码(目前仅支持 Base64)的元数据。这一设计的具体实现位于 internal/action/binary.go 的
secFromBytes函数:sec := secrets.NewAKV() sec.Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", filepath.Base(src))) sec.Set("Content-Transfer-Encoding", "Base64") var written int encoder := base64.NewEncoder(base64.StdEncoding, sec) n, err := encoder.Write(in) ... n, err = sec.Write([]byte("\n"))要点拆解:
- 条目载体:使用
secrets.NewAKV()构造的 AKV(attributes-key-value)格式条目,其结构定义在 pkg/gopass/secrets/akv.go,内部持有密码字段、键值对映射和原始字符串缓冲区;- 来源元数据:
Content-Disposition: attachment; filename="STDIN",文件名取输入来源的filepath.Base(从管道输入时即为STDIN,从文件拷贝时为文件名);- 编码元数据:
Content-Transfer-Encoding: Base64,声明载荷的编码方式;- 载荷编码:使用 Go 标准库
encoding/base64的StdEncoding将原始字节写入条目,并在末尾追加一个换行符,形成上文示例中MjM0Cg==那样的单行 Base64 文本。写入条目的提交信息固定为
"Read secret from STDIN"(见 internal/action/binary.go),在基于 git 的存储后端中,这条信息会成为该次变更的 commit message。源码级的读取与解码流程
读取方向的核心逻辑同样在 internal/action/binary.go 的
binaryGet中,它被Cat和Sum(SHA256 校验和)两个命令共用:sec, err := s.Store.Get(ctx, name) ... if !isBase64Encoded(sec) { // need to use sec.Bytes() otherwise the first line is missing. return sec.Bytes(), nil } body := sec.Body() buf, err := base64.StdEncoding.DecodeString(body)解码前先做编码探测:
isBase64Encoded(internal/action/binary.go)会同时检查Content-Transfer-Encoding与content-transfer-encoding两种大小写变体,只要任一值为base64就按 Base64 解码;否则回退为直接返回原始字节。这个兼容分支意味着gopass cat也能读取由insert等命令写入的普通文本条目(此时原样透传,不做解码)。读取到解码字节后,
Cat通过fmt.Fprint(stdout, string(buf))输出到 STDOUT;若条目不存在或解密失败,则返回Decrypt级别的错误(见 internal/action/binary.go)。命令入口经由 internal/action/handler_shims.go 的Action.Cat转发到binaryHandler.Cat。与
insert的区别文档专门辟出一节说明与
insert的差异:In contrast to
insertit handles any kind of>赞
- 应用安全
- 开发工具
【免费下载链接】gopass
The slightly more awesome standard unix password manager for teams
相关推荐
Caire管道命令应用:stdin/stdout的高效图像处理
Caire管道命令应用:stdin/stdout的高效图像处理 你还在为传统图像处理工具的繁琐流程而烦恼吗?需要频繁保存临时文件、手动管理输入输出路径?Cair
图像处理chezmoi 模板函数 `gopassRaw`:从 gopass 读取原始密码与二进制数据的完整指南
chezmoi 模板函数 gopassRaw :从 gopass 读取原始密码与二进制数据的完整指南 gopassRaw 是 chezmoi 提供的 gopas
开发工具CLI配置管理chezmoi gopass 模板函数:在 dotfiles 中安全注入 gopass 密码凭据
chezmoi gopass 模板函数:在 dotfiles 中安全注入 gopass 密码凭据 gopass 是 chezmoi 内置的密码管理器模板函数之一
开发工具CLI配置管理