当前位置: 首页 > news >正文

【C/C++】explicit_bzero

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
#endifnamespace secure {// 可移植 secure_memzero 封装
inline void memzero(void* ptr, size_t len) {if (!ptr || len == 0) return;#if defined(_WIN32)// Windows 安全 APISecureZeroMemory(ptr, len);#elif defined(__GLIBC__) && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 25))// glibc 2.25+ 提供 explicit_bzeroexplicit_bzero(ptr, len);#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__)// macOS / BSD 系统一般也有 explicit_bzeroexplicit_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 需替代方案
推荐场景密码学、加密库、认证信息清除等
http://www.lryc.cn/news/600643.html

相关文章:

  • 《Java 程序设计》第 6 章 - 字符串
  • Zookeeper的简单了解
  • 安卓学习记录1——持续更新ing
  • Java基础day17-LinkedHashMap类,TreeMap类和集合工具类
  • linux下变更mysql的数据文件目录
  • 基于粒子群算法优化高斯过程回归(PSO-GPR)的多输出回归
  • 基于MySQL实现基础图数据库
  • React入门指南——指北指南(第二节)
  • SpringMVC相关基础知识
  • RustFS for .NET 演示项目深度解析:构建 S3 兼容的分布式存储应用
  • 计划任务(at和cron命令介绍及操作)
  • 《用于几何广义断层触觉传感的图结构超分辨率:在仿人面部的应用》论文解读
  • 一款基于react-native harmonyOS 封装的【文档】文件预览查看开源库(基于Harmony 原生文件预览服务进行封装)
  • 深入剖析 MetaGPT 中的提示词工程:WriteCode 动作的提示词设计
  • Blender入门笔记(一)
  • 简单实现支付密码的页面及输入效果
  • Sql server查询汇总补缺月份
  • 【iOS】网易云仿写
  • 基于深度学习的胸部 X 光图像肺炎分类系统(七)
  • springboot 前后端,基于票据+SHA派生密钥+SM4加解密
  • 经典IDE之Turbo C
  • 基于MC9S12XEP100的整车控制器(VCU)设计
  • 【Zephyr】Window下的Zephyr编译和使用
  • Redis的数据淘汰策略是什么?有哪些?
  • 资产负债表及其数据获取
  • 【LeetCode 热题 100】79. 单词搜索——回溯
  • 进阶数据结构:用红黑树实现封装map和set
  • element-plus安装以及使用
  • 机器人仿真(2)Ubuntu24.04下RTX5090配置IsaacSim与IsaacLab
  • Java实现大根堆与小根堆详解