deadpoets/secmem

GitHub: deadpoets/secmem

一个纯 Go 实现的机密内存库,通过堆外锁定内存、内核隔离和保证擦除来保护进程内的私钥、token 和密码等敏感数据。

Stars: 1 | Forks: 0

# secmem [![Go Reference](https://pkg.go.dev/badge/github.com/deadpoets/secmem.svg)](https://pkg.go.dev/github.com/deadpoets/secmem) [![CI](https://static.pigsec.cn/wp-content/uploads/repos/cas/ad/ad5834178f7599af9fdda11629d49cae07f2997beec49821b2920eff5bfd50e7.svg)](https://github.com/deadpoets/secmem/actions/workflows/ci.yml) [![Go Report Card](https://goreportcard.com/badge/github.com/deadpoets/secmem)](https://goreportcard.com/report/github.com/deadpoets/secmem) 强化内存中的机密信息 —— 让私钥、token 和密码远离 Go 的垃圾回收堆,将其置于操作系统锁定且被排除在 swap 之外的内存页中,并在平台允许的情况下,使其免于出现在 core dumps 及其他进程中。释放时,字节会通过架构专用的例程被擦除,并且仅能通过借用闭包访问,从而确保明文在完成使命后即刻消亡。 纯 Go 实现 (`CGO_ENABLED=0`),仅依赖于 `golang.org/x/sys`。 ## 诚信为先 每一项保证都按平台逐一说明,并明确指出其**无法**防范的内容。一个夸大其安全保证的安全库比没有安全库更糟糕。因此: - 平台无法提供的保护会通过 [`Capabilities`](https://pkg.go.dev/github.com/deadpoets/secmem#Capabilities) 进行**报告**, 绝不会默默跳过。在启动时调用一次 [`Probe`](https://pkg.go.dev/github.com/deadpoets/secmem#Probe) 即可查看当前生效的保护措施。 - 没有可锁定堆外内存的平台会**响亮地报错** (`ErrNoSecureMemory`),而不是退化为不受保护的堆内存 —— 除非你通过 `WithInsecureFallback()` 显式选择允许。 - 下文所述的每一项声明都经过了测试验证。guard pages 确实会触发错误;`memfd_secret` 的隔离已通过 `/proc/self/mem` 进行检查;擦除、脱敏和不触发 panic 的承诺均已通过 fuzz 测试。关于测试套件运行过的内核列表,请参见 [`KERNELS.md`](KERNELS.md)。 ## 安装 ``` go get github.com/deadpoets/secmem ``` ## 快速开始 ``` buf, err := secmem.NewBuffer(rawKey) // rawKey is wiped after the copy if err != nil { return err } defer buf.Destroy() // always defer immediately err = buf.WithBytesErr(func(borrowed []byte) error { // borrowed is valid ONLY inside this closure — never store it. return sign(borrowed, msg) }) ``` 对于你持有并可能记录到日志中的值,请将它们包装在 [`Secret`](https://pkg.go.dev/github.com/deadpoets/secmem#Secret) 中:它会通过 `fmt`、`encoding/json` 和 `log/slog` 将其渲染为 `[REDACTED]`。若要对自由格式的日志文本进行脱敏,[`redact`](https://pkg.go.dev/github.com/deadpoets/secmem/redact) 子包提供了一个 `slog.Handler` 包装器。 ## 平台保证矩阵 `✓` 强制执行 · `⚠` 尽力而为(报告失败,但非致命错误) · `✗` 未提供 · **LOUD** 仅在显式选择时启用。此表是威胁模型的核心;关于这些措施都无法防范的内容,请参见 [THREAT-MODEL.md](THREAT-MODEL.md)。 | 保护措施 | linux/amd64·arm64 (≥5.14) | linux (较旧 / 32位) | darwin | windows | 其他 | |---|---|---|---|---|---| | 远离 Go 堆 | ✓ memfd_secret | ✓ mmap | ✓ mmap | ✓ VirtualAlloc | **LOUD** 仅限堆 | | 无 swap (已锁定) | ✓ | ✓ mlock | ✓ mlock | ✓ VirtualLock | ✗ | | 内核隔离 (对 root / ptrace / `/proc//mem` 不可见) | ✓ memfd_secret | ✗ (退化为 mlock) | ✗ | ✗ | ✗ | | 排除在崩溃转储之外 | ⚠ MADV_DONTDUMP | ⚠ MADV_DONTDUMP | ✗ | ⚠ WER 排除 | ✗ | | 不通过 fork 继承 | ⚠ MADV_DONTFORK | ⚠ MADV_DONTFORK | ✗ | n/a | ✗ | | 无 THP/KSM 机密副本 | ✓ madvise | ✓ madvise | n/a | n/a | ✗ | | 销毁时保证擦除 | ✓ asm + 缓存刷新 | ✓ (amd64/arm64 asm; 否则 ⚠ 常数时间) | ✓ asm | ✓ asm (amd64) | ⚠ 常数时间存储 | | Guard pages + 溢出 canary | ✓ | ✓ | ✓ | ✓ | ✗ (堆回退) | | 寄存器 + 栈 + 堆清理 ([`Scrub`](https://pkg.go.dev/github.com/deadpoets/secmem#Scrub)) | ✓ 需开启 `GOEXPERIMENT=runtimesecret` | ✓ 如果设置 (amd64/arm64);否则帧清理 | 仅限帧清理 | 仅限帧清理 | 帧清理 / ✗ | | 密封时加密 ([`Seal`](https://pkg.go.dev/github.com/deadpoets/secmem#SecureBuffer.Seal)) | ✗ | ✗ | ✗ | ✓ CryptProtectMemory | ✗ | | 进程强化 ([`HardenProcess`](https://pkg.go.dev/github.com/deadpoets/secmem#HardenProcess)) | ✓ dumpable=0, no-new-privs | ✓ | ✗ | ✓ ACG + 严格句柄 | ✗ | | 响亮报错,从不默默降级 | ✓ | ✓ | ✓ | ✓ | ✓ (**LOUD** 显式选择) | 该套件已在真实的 **linux/amd64 和 linux/arm64** 硬件上执行, 涵盖内核版本从 5.10 到 7.x(参见 [`KERNELS.md`](KERNELS.md))。在 arm64 (Ampere Altra) 上,`memfd_secret` L4 路径、guard-page 错误、 `/proc/self/mem` 隔离证明以及架构专用的擦除汇编代码 均测试通过。`memfd_secret` 是否生效取决于内核的 `CONFIG_SECRETMEM`,而不仅仅是版本号 —— 如果缺失,secmem 会针对每一次分配如实报告“回退”并使用 `mmap`+`mlock`。 guard pages 和 canary 是一种**内存安全漏洞捕获器,而非机密性控制手段** —— 它们能捕获意外的上溢/下溢,但对于拥有特权的进程内存读取者却无能为力(那是 `memfd_secret` 的职责)。Windows 密封状态密码提高防范休眠机密内存转储的门槛;它并非冷启动保护。两者在 godoc 和威胁模型中均有详细说明。 ## 模块 - **`secmem`** (当前模块) —— 包含 `SecureBuffer`、`SecureArena`、`Secret`、 `Capabilities`/`Probe`、`Scrub` 以及进程强化辅助工具。仅依赖于 `golang.org/x/sys`。 - **`secmem/redact`** —— 包含用于边界级别日志清理的 `Sanitizer` 和 `slog.Handler`。仅使用标准库。 ## 文档 完整的 API 文档、每个符号可运行的 `Example` 以及每个符号的保证说明均位于 [pkg.go.dev](https://pkg.go.dev/github.com/deadpoets/secmem)。关于端到端 程序,[`examples/`](examples/) 提供了一个密码注册/登录流程以及一个 可用的、经过强化的 SSH 代理 —— 每一个都在真实的 I/O、 并发和关机操作下组合使用了该库。请从 包概述开始阅读,然后通过 [`THREAT-MODEL.md`](THREAT-MODEL.md) 了解限制, 通过 [`TESTING.md`](TESTING.md) 查看每个声明是如何被证明的(或为何无法被证明), 通过 [`ENVIRONMENTS.md`](ENVIRONMENTS.md) 了解在 root / 非 root / 容器下的行为,通过 [`KERNELS.md`](KERNELS.md) 了解该套件运行过的 Linux 内核, 并通过 [`WINDOWS.md`](WINDOWS.md) 了解 Windows 版本/构建信息。 ## 贡献 欢迎提交 Bug 修复、强化改进以及无回归的性能提升 —— 请参阅 [CONTRIBUTING.md](CONTRIBUTING.md) 了解工作流(每一个 PR,包括 维护者的,都要经过审查和 CI 测试)。发现了漏洞?请参阅 [SECURITY.md](SECURITY.md) —— 请勿将其作为公开 issue 提交。 参与受[行为准则](CODE_OF_CONDUCT.md)约束。 ## 许可证 Apache-2.0。请参阅 [LICENSE](LICENSE)。
标签:EVTX分析, Go语言, HTTP工具, 内存安全, 日志审计, 机密保护, 程序破解, 系统编程, 防御性编程, 防御绕过