Rust:Hash trait

在Rust中,Hash trait用于计算一个类型的哈希值。 通过在类型上实现Hash trait来 自定义 哈希计算的方式。

假设我们有一个表示区块的结构体Block,我们可以为它实现Hash trait来计算区块的哈希值。以下是一个例子:

Rust 复制代码
use std::hash::{Hash, Hasher};

#[derive(Debug,Hash)]
struct Block {
    index: u32,
    timestamp: u64,
    data: String,
    previous_hash: String,
}

当然我们也可以通过手动为其实现Hash trait,其实上面的宏自动添加的就是下面的代码,为Block结构体实现了 hash 方法,之后我们就可以通过调用该方法求哈希了

Rust 复制代码
use std::hash::{Hash, Hasher};

#[derive(Debug)]
struct Block {
    index: u32,
    timestamp: u64,
    data: String,
    previous_hash: String,
}
 
impl Hash for Block {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.index.hash(state);
        self.timestamp.hash(state);
        self.data.hash(state);
        self.previous_hash.hash(state);
    }
}

在这个例子中,我们为Block类型实现了Hash trait。并且对里面的字段indextimestampdataprevious_hash来计算哈希值。

在计算一个结构体的hash时,需要创建一个Hasher对象,

rust 复制代码
let mut hasher = DefaultHasher::new();

然后调用实现了Hash trait的结构体的hash方法。例如,后面我们通过调用 Block 结构体的 hash 方法

Rust 复制代码
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};

let mut hasher = DefaultHasher::new();
let block = Block { index: 1, timestamp: 1630560392, data: "Block data".to_string(), previous_hash: "0000000000000000000000000000000000000000000000000000000000000000".to_string() };
block.hash(&mut hasher);

let hash = hasher.finish();
println!("Hash is {:x}!", hash);

这段代码首先创建了一个DefaultHasher对象,然后使用Block类型的hash方法来更新哈希器的状态。最后,我们调用finish方法来获取最终的哈希值。

这个时候大家可能会好奇,在这里生成的 hash 到底是什么样的呢?是不是我们所知悉的区块链中的哈希类型呢?

其实不然,在这里的 hash 并不是我们所熟知的 u256 类型 而是 u64 类型,相信如果大家跟着写的话大家都看到了编译器对 hash 的类型推断。

为什么呢?因为在哈希算法中,输出的哈希值的长度是由具体的哈希算法决定的。例如,MD5生成的哈希值长度为128位,SHA-1生成的哈希值长度为160位,SHA-256生成的哈希值长度为256位等等。

在这里生成的 u64 类型的哈希,是因为它使用了 SipHasher13算法 ,SipHash是一种加密哈希函数,它对于短输入有很好的性能,因此常常被用于哈希表。

然而,需要注意的是,哈希值的长度和哈希算法的安全性有关。一般来说,哈希值越长,碰撞的概率就越低,因此哈希算法就越安全。所以,在选择哈希算法时,需要根据具体的应用场景和安全需求来决定使用哪种哈希算法

下面是DefaultHasher的源码: 它是哈希算法的一部分,用于计算最终的哈希值。

rust 复制代码
pub struct DefaultHasher(SipHasher13);

下面则是finish方法内的实现

rust 复制代码
fn finish(&self) -> u64 {
        let mut state = self.state;

        let b: u64 = ((self.length as u64 & 0xff) << 56) | self.tail;

        state.v3 ^= b;
        S::c_rounds(&mut state);
        state.v0 ^= b;

        state.v2 ^= 0xff;
        S::d_rounds(&mut state);

        state.v0 ^ state.v1 ^ state.v2 ^ state.v3
    }

这个函数首先复制了当前的哈希状态,然后根据输入数据(self.lengthself.tail)计算出一个新的值b。然后,它更新哈希状态,并使用S::c_roundsS::d_rounds函数进行一些混淆操作。最后,它返回四个状态值的异或结果作为最终的哈希值。

所以,该trait在实现 区块链方面的哈希值 不太行,因为太短,不够安全,但是用来实现哈希表 是明智的选择。from Pomelo_刘金,转载请注明原文链接。感谢!

相关推荐
向上的车轮12 小时前
从零实现一个高性能 HTTP 服务器:深入理解 Tokio 异步运行时与 Pin 机制
rust·系统编程·pin·异步编程·tokio·http服务器
AI自动化工坊16 小时前
OpenFang实战指南:用Rust构建高并发AI Agent操作系统
开发语言·人工智能·ai·rust·agent·ai agent
gsls20080817 小时前
tauri开发环境搭建
rust·npm·tauri
Binarydog_Lee17 小时前
Tauri2 开发入门:应用是如何启动的
前端·rust·tauri
Web3VentureView18 小时前
SYNBO 已上线 BitMart 交易所,Synbo Camp 同步开启
人工智能·区块链·媒体·加密货币·synbo
changzehai19 小时前
RustRover + J-Link 一键调试 STM32 教程
stm32·单片机·嵌入式硬件·rust·rustrover
咸甜适中19 小时前
rust序列化和反序列化(json、yaml、toml)详解
开发语言·rust·json
IT 行者20 小时前
CentOS 下源码编译安装完整版 Redis 8.0 指南(附 Rust 工具链详解)
redis·rust·centos
暴躁小师兄数据学院20 小时前
【WEB3.0零基础转换笔记】Rust编程篇-第4讲:控制流
开发语言·笔记·rust·web3·区块链·智能合约
MicroTech202520 小时前
量子驱动强化学习(QRBT):微算法科技(NASDAQ :MLGO)区块链交易处理的可扩展解决方案
科技·区块链