【C/C++】explicit_bzero

发布于:2025-07-27 ⋅ 阅读:(16) ⋅ 点赞:(0)

explicit_bzero

explicit_bzero 是一个为了解决 memset 在安全清除内存场景中可能被优化器移除的问题而设计的函数,广泛用于安全编程中,比如密码、密钥清除等。


Introduce

头文件

#include <string.h>

函数原型

void explicit_bzero(void *s, size_t n);

功能说明

将内存区域 s 开始的 n 个字节强制清零(写入 0),确保不会被编译器优化掉


为什么不能用 memset

当你写:

char key[32];
// ... 使用 key ...
memset(key, 0, sizeof(key));

有些编译器会发现 key 后面就不再使用,于是优化器会移除 memset 调用,导致密码/密钥未被真正擦除,造成信息泄露风险。

explicit_bzero 的实现避免了这一问题:

  • 使用 volatile 指针或编译器 barrier;
  • 或直接调用外部函数(编译器无法内联);
  • 保证操作不可优化,满足安全清除需求

可用平台

平台 是否支持 explicit_bzero
✅ FreeBSD 原生支持
✅ OpenBSD 原生支持(首发平台)
✅ glibc >= 2.25(2017) 支持
✅ macOS 10.12+ 可用
🚫 Windows 不支持(用 SecureZeroMemory

用法示例

#include <string.h>

int main() {
    char secret[32] = "TopSecretPassword123!";

    // 使用 secret 做某些操作...

    // 清除 secret(防止泄露)
    explicit_bzero(secret, sizeof(secret));

    return 0;
}

📌 即使 secret 后续没有再用,这个清除也不会被优化掉!


bzero 区别?

函数 是否会被优化器移除 是否已废弃 推荐使用
memset ✅ 有风险 ❌ 不用于清除敏感数据
bzero ✅ 有风险 ✅ 已废弃(非标准)
explicit_bzero ❌ 安全 ✅ ✅ ✅

Windows 等平台

Windows 没有 explicit_bzero,可以用:

#include <windows.h>
SecureZeroMemory(ptr, size);

或者自己写:

void secure_memzero(void* p, size_t len) {
    volatile unsigned char* vp = (volatile unsigned char*)p;
    while (len--) {
        *vp++ = 0;
    }
}

跨平台、安全、可靠的 explicit_bzero 封装实现

  • Linux(glibc >= 2.25)使用系统 explicit_bzero
  • macOS 使用 explicit_bzerobzero
  • Windows 使用 SecureZeroMemory
  • 其他平台使用手动 volatile 写法

跨平台安全内存清除封装

#pragma once

#include <cstddef>  // for size_t

#if defined(_WIN32)
    #include <windows.h>
#elif defined(__has_include)
    #if __has_include(<string.h>)
        #include <string.h>
    #endif
#endif

namespace secure {

// 可移植 secure_memzero 封装
inline void memzero(void* ptr, size_t len) {
    if (!ptr || len == 0) return;

#if defined(_WIN32)
    // Windows 安全 API
    SecureZeroMemory(ptr, len);

#elif defined(__GLIBC__) && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 25))
    // glibc 2.25+ 提供 explicit_bzero
    explicit_bzero(ptr, len);

#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__)
    // macOS / BSD 系统一般也有 explicit_bzero
    explicit_bzero(ptr, len);

#else
    // 手动 volatile 写法,防止优化器移除
    volatile unsigned char* p = reinterpret_cast<volatile unsigned char*>(ptr);
    while (len--) {
        *p++ = 0;
    }
#endif
}

} // namespace secure

使用方式

#include "secure_memzero.hpp"

int main() {
    char password[32] = "MySecretPassword";

    // ... 使用 password ...

    // 安全清除
    secure::memzero(password, sizeof(password));

    return 0;
}

测试建议

  1. Release 模式下测试,确保 secure::memzero 不被优化掉。
  2. 检查编译器汇编输出(例如 objdump -d)确保有写入指令。
  3. 如在密码模块中使用,建议配合内存保护机制(如 mlock)以防 swap 泄露。

优点

特性 描述
安全 防止编译器优化清零操作
跨平台 兼容 Linux/macOS/Windows/FreeBSD 等系统
无依赖 不依赖 C11 memset_s
可内联 单头文件,适用于库内/项目中任意使用

总结

特性 说明
安全 不会被编译器优化
用途 清除密码、私钥等敏感数据
可移植性 glibc 2.25+、BSD、macOS 支持,Windows 需替代方案
推荐场景 密码学、加密库、认证信息清除等

网站公告

今日签到

点亮在社区的每一天
去签到