首页 > 系统相关 >短小精悍(5) - Rust内存清零库zeroize介绍

短小精悍(5) - Rust内存清零库zeroize介绍

时间:2023-12-28 13:11:41浏览次数:49  
标签:Zeroize read secret zeroize let 清零 ptr Rust


今天带来的是一个“短小精悍”的库:zeroizezeroize可以在确保不被编译器优化的前提下安全高效地清空一段内存,适合在保密应用内使用。

用法

zeroize的核心用法很简单:

use std::string::String;
use zeroize::Zeroize;

fn main() {
    let mut user_password = String::from("qwertyuiop");
    user_password.zeroize();
}

你也可以为自己的类型增加zeroize的支持(需要启用derive特性):

use zeroize::Zeroize;

#[derive(Zeroize)]
struct MyStruct([u8; 32]);

甚至可以通过derive名为ZeroizeOnDrop的trait,来让自己的类型在被销毁时自动从内存擦除:

use zeroize::{Zeroize, ZeroizeOnDrop};

#[derive(Zeroize, ZeroizeOnDrop)]
struct MyStruct([u8; 32]);

接下来,我们来使用unsafe代码来检查一下zeroize的正确性,即安全清零、不被优化:

use zeroize::Zeroize;

#[derive(Zeroize)]
struct SecretInfomation([u8; 4]);

fn main() {
    let secret = SecretInfomation([2u8, 4, 6, 8]);

    let ptr: usize = secret.0.as_ptr() as usize;

    // 读取一次secret中的数据,现在secret还可以被正常访问
    unsafe {
        let read_secret = std::slice::from_raw_parts(ptr as *const u8, 4);
        println!("Secret before zeroize: {:?}", read_secret);
    }

    // secret.zeroize();
    drop(secret);

    // 再读取一次secret中的数据,现在secret没有被置零
    unsafe {
        let read_secret = std::slice::from_raw_parts(ptr as *const u8, 4);
        println!("Secret without zeroize: {:?}", read_secret);
    }

}

实验结果是:

现在我们在drop对象之前调用一次zeroize

use zeroize::Zeroize;

#[derive(Zeroize)]
struct SecretInfomation([u8; 4]);

fn main() {
    let mut secret = SecretInfomation([2u8, 4, 6, 8]);

    let ptr: usize = secret.0.as_ptr() as usize;

    // 读取一次secret中的数据,现在secret还可以被正常访问
    unsafe {
        let read_secret = std::slice::from_raw_parts(ptr as *const u8, 4);
        println!("Secret before zeroize: {:?}", read_secret);
    }

    secret.zeroize();
    drop(secret);

    // 再读取一次secret中的数据,现在secret已经被置零
    unsafe {
        let read_secret = std::slice::from_raw_parts(ptr as *const u8, 4);
        println!("Secret after zeroize: {:?}", read_secret);
    }

}

这次,secret的值被置0,并且在未优化和已优化两种情况下都持续有效。

用途

既然是即将被drop的数据,为什么我们还要特意清零它呢?在一个理想的完美世界里,这样做确实是无意义的。但是如果黑客能够利用漏洞读取计算机未初始化的内存(这不是如果,这是不可避免的事实),那么仍然留在内存里的敏感数据便会直接成为黑客的囊中之物。对一些加密应用、保密应用、处理各类机密的程序来说,这种风险是致命、不容忽视的。在低级加密软件指南里,有更为详细和专业的说明。

遗憾的是,编译器并不能保证我们直接使用memset等接口执行的清零操作总是不被优化。在C中,我们可以使用volatile关键字来保证清零操作不会被优化,例如这是一个载于How to zero a buffer的例子:

static void * (* const volatile memset_ptr)(void *, int, size_t) = memset;

static void secure_memzero(void * p, size_t len)
{
  (memset_ptr)(p, 0, len);
}

Rust当然也提供了类似的关键字。在标准库函数core::ptr::write_volatile中,我们可以易失性地写入指定的内存地址。zeroize便为我们封装了这样的操作,并向我们提供了Rust风格的、高级的、易用的Zeroizetrait。

此外,zeroize是Rust Crypto项目的一个组成部分,这个项目为Rust实现了大量的加密算法。同样的,这个项目中的算法实现也都使用了zeroize来清除使用完成的内存。

标签:Zeroize,read,secret,zeroize,let,清零,ptr,Rust
From: https://www.cnblogs.com/cinea/p/17932476.html

相关文章

  • mrml mjml 的rust 实现
    mrml是mjml的rust实现,同时还提供了webassembly的支持,当然比较强大的是mrml同时也实现了pythonbindingwebassembly使用代码const{Engine}=require("mrml");constengine=newEngine();constresult=engine.toHtml("<mjml><mj-body>HelloWor......
  • [记]在rust中使用xml,xml的序列化与反序列化
    序在rust中有好几个xml库,但我个人比较推荐的是quick_xml库,这个库的序列化和反序列化使用体验比较好。启用quick_xml的featurequick-xml={version="0.31.0",features=["serde","serialize"]}serde={version="1.0",features=["derive"]}qucik_mxl的宏体验依......
  • 短小精悍(4) - Rust操作系统随机数getrandom库介绍
    今天带来的是另一个“短小精悍”的库:getrandom。它的作用是从操作系统提供的随机数源获得一段随机数。用法getrandom的用法很简单,唯一需要了解的就是它内部的同名函数:pubfngetrandom(dest:&mut[u8])->Result<(),Error>它将会向dest中填充来自操作系统的随机数。示例:......
  • Rust爬取大A股票数据.rs
    externcratesimple_excel_writerasexcel;useexcel::*;fnmain()->Result<(),Box<dynstd::error::Error>>{  leturl:&str="http://94.push2.eastmoney.com/api/qt/clist/get?cb=jQuery1124040399874179311124_1685159655748&pn......
  • Rust error : usize 类型不能进行 - 操作
    return(-low-1asisize)asisize;cannotapplyunaryoperator-Rust编写程序时候usize类型进行-1运算时报的错误写了下BinarySearch,对于if判断修正为平衡版本,同时解决了取得的midVal已经获取其下标,不必等其缩小完边界。以下是第一种较差的实现方式。fnbinar......
  • Windows 安装 Rust 并设置镜像加速
    目录下载rustup-init.exe(Rust安装工具)使用镜像加速rustup安装安装Rust安装标准库源码使用镜像加速cargo包下载安装结果确认更新、卸载和文档查看参考文档下载rustup-init.exe(Rust安装工具)下载安装程序https://www.rust-lang.org/tools/install,我选的是64位:使用镜像加速rustu......
  • 37. 干货系列从零用Rust编写负载均衡及代理,负载均衡中try_files实现
    wmproxywmproxy已用Rust实现http/https代理,socks5代理,反向代理,静态文件服务器,四层TCP/UDP转发,七层负载均衡,内网穿透,后续将实现websocket代理等,会将实现过程分享出来,感兴趣的可以一起造个轮子项目地址国内:https://gitee.com/tickbh/wmproxygithub:https://github.com/......
  • rust call sqlite3 error: linking with `link.exe` failed: exit code: 1181
    rustcallsqlite3error:linkingwithlink.exefailed:exitcode:1181声明:本文禁止csdn.net及所有所有子网站转载。禁止以营利性为目的的转载。报错error:linkingwith`link.exe`failed:exitcode:1181......
  • Windows下使用rust调用SQLite3
    Windows下使用rust调用SQLite3声明:本文禁止csdn.net及所有所有子网站转载。禁止以营利性为目的的转载。userusqlite::{Connection,Result};#[derive(Debug)]structPerson{id:i32,name:String,data:Option<Vec<u8>>,}fnmain()->Result<()>{......
  • rust 过程宏
    简介Rust编程语言里面有两种宏系统,一种是声明宏(DeclarativeMacros),另一种为过程宏(ProceduralMacros)。声明宏和过程宏是两种基本上完全不一样的宏系统,编写的方式也完全不一致,使用方式除了函数式外也不一致。关于声明宏学习,Rust宏小册里面有比较详细的说明,这里不再啰嗦。而对于......