kczpl/anamorph
GitHub: kczpl/anamorph
一款基于图像 LSB 隐写术的桌面工具,将 AES-256-GCM 加密信息隐藏于 PNG 像素中,通过密码或 YubiKey 硬件触摸解锁。
Stars: 3 | Forks: 0
# anamorph


将加密信息隐藏在普通图像中。
## 它是什么
一个小型桌面应用程序。你给它一张图片和一条信息,它会还给你一个
看起来一模一样、但将信息隐藏在像素中的 PNG。
任何拥有该 PNG 和密码——或正确的 YubiKey——的人都可以读取
这条信息。对其他人而言,它只是一张图片。
一切皆由 Go 编写。两个依赖项:用于 GUI 的 [Fyne](https://fyne.io)
和用于 PIV 智能卡访问的 [piv-go](https://github.com/go-piv/piv-go),
后者仅用于 YubiKey 锁定。其他一切——AES、ECDH、HKDF、
PBKDF2、PNG 和 JPEG 处理——都使用 Go 标准库。
## 工作原理
- 信息使用 AES-256-GCM 加密。密钥由你的密码通过
PBKDF2-SHA256 经过 60 万次迭代生成。
- 加密后的 payload 被写入图像 R、G 和 B 通道的最低有效位中。
Alpha 通道保持不变。
- 结果始终保存为 PNG。像 JPEG 这样的有损格式会
破坏隐藏的比特位。
- 密码是可选的。没有密码,信息仍然会被隐藏并受到完整性保护,
只是不保密。
- 你可以使用 YubiKey 锁定信息,而不是使用密码。应用程序
在 YubiKey 的 PIV 小程序中生成一个 P-256 密钥——它永远不会离开
硬件——并加密到其公钥部分(ECDH 加上 HKDF-SHA256,
使用相同的 AES-256-GCM)。只有那个 YubiKey 才能解密图像,并且
需要物理触摸:密钥会闪烁,信息保持封存状态,直到
你点击它,因此丢失或被盗的密钥无法静默打开任何东西。
- 两个 YubiKey 可以配对:应用程序生成一个共享密钥并
将其写入两者,因此任一密钥都可以打开相同的图像。配对一次,
将一个密钥交给另一个人,你们之间就建立了一个硬件锁定的
通道。在配对过程中,共享密钥会短暂存在于
计算机的内存中——这是让它存在于两张卡上的代价。
- 应用程序创建的每个密钥都带有一个名称,例如
`anamorph pair 2026-07-19 3f9a1c`,存储在插槽的证书中,
因此应用程序——以及 `ykman piv info`——始终可以告诉你密钥的
来源。配对的密钥共享相同的名称。
一张 500×500 的图像可以容纳约 93 KB 的信息。GCM 标签兼作
错误密码检测,因此应用程序可以告诉你密码是错误的,
而不是输出乱码。

## 下载
从[发布页面](https://github.com/kczpl/anamorph/releases)获取适合你平台的预编译二进制文件——
无需 Go 工具链。这是将构建版本交给与你配对 YubiKey 的另一个人的简单方法。
构建版本未经付费开发者证书签名,因此每个
系统在首次启动时都会发出警告。这是预料之中的;以下是如何
跳过警告的方法:
- **macOS**:右键点击应用程序并选择**打开**,然后在对话框中再次选择
**打开**——或者运行一次 `xattr -cr anamorph.app`。之后它
就会正常启动。
- **Windows**:SmartScreen 会显示一个蓝色横幅。点击**更多信息**,然后
点击**仍要运行**。
- **Linux**:解压 tarball 并运行 `anamorph` 二进制文件。YubiKey
锁定在运行时需要 PC/SC——安装 `libpcsclite`(Debian/Ubuntu:
`libpcsclite1`)并启动 `pcscd` 服务。密码锁在没有它的情况下也能
工作。
## 从源码构建
你需要 Go 1.26+,在 macOS 上还需要 Xcode Command Line Tools
(`xcode-select --install`)。Fyne 使用 cgo,因此在每个
平台上都需要 C 编译器。YubiKey 支持与 PC/SC 通信——内置于 macOS 和
Windows;在 Linux 上安装 `libpcsclite-dev` 并运行 `pcscd` 服务。
```
git clone https://github.com/kczpl/anamorph
cd anamorph
go run .
```
就这样。如果你使用 [just](https://github.com/casey/just):
```
just setup # one-time: installs the fyne CLI
just run # run from source
just test # go test ./... -race -cover
just build # vet + test + package anamorph.app
just install # build and install into /Applications (macOS)
```
`just package-mac` 会生成包含通用 macOS 构建
(Apple Silicon + Intel)的 `dist/anamorph-macos.zip`。应用程序经过了 ad-hoc 签名,但没有经过
公证,因此在首次启动时 macOS 会报错——可以在系统设置 → 隐私与安全性中点击
**仍要打开**,或者运行一次
`xattr -cr anamorph.app`。
Windows 和 Linux 构建也可以工作,但必须在目标
OS 上(或使用 [fyne-cross](https://github.com/fyne-io/fyne-cross))进行编译,因为
Fyne 需要 cgo。
## 用法
**隐藏**:放入一个 PNG 或 JPEG,输入你的信息并选择一个锁——
密码或 YubiKey。一个新的 YubiKey 提供了一个选择:仅为此
计算机进行设置,或者配对两个 YubiKey 以便两个人可以交换图像——
应用程序会引导你依次插入每个密钥。保存,你
就会得到一个新的 PNG。
**显示**:放入一个由 anamorph 制作的 PNG。应用程序会告诉你它
需要什么——密码,或者端口中正确的 YubiKey——并显示
信息。
### YubiKey 流程
角落里的绿点表示已插入设置好的 YubiKey。在“隐藏”选项卡中
将信息锁定到它;在“显示”选项卡中,应用程序会通过名称找到正确的
密钥,并且信息会保持封存状态,直到你物理上触摸它——
密钥在等待时会闪烁。
## 代码布局
- `internal/stego` - 比特位输入,比特位输出。在图像中隐藏一个带长度前缀的 payload 并将其取回。
- `internal/crypt` - AES-256-GCM 的密封和开启。
- `internal/vault` - 将两者结合在一起,首先将任何解码后的
图像标准化为干净的 NRGBA 画布。
- `internal/yubikey` - 在插入的 YubiKey 上查找、创建或配对 anamorph 密钥,并运行只有硬件才能完成的操作:解密的 ECDH 部分。
- `internal/ui` - Fyne 界面。`main.go` 只是调用 `ui.Run()`。
## 名称由来
源自 [anamorphosis](https://en.wikipedia.org/wiki/Anamorphosis)——一种扭曲的
图像,只有从正确的角度或通过正确的设备查看时,才能解析出清晰的
图片。这里的理念是一样的:对其他人来说,它只是
一张图片;以正确的方式查看它——使用应用程序和密码——
信息就会出现。
![]() |
![]() |
![]() |
![]() |
标签:EVTX分析, 日志审计



