Найти в Дзене
Один Rust не п...Rust

Хеш-функции на Rust

Для чего нужна данная статья? : Написать код который содержит: ✅ Одновременное использование нескольких хеш-алгоритмов (SHA-256, BLAKE3, FNV, xxHash)
✅ Генерацию HMAC (SHA-256) для безопасной аутентификации
✅ Асинхронную обработку хеширования с tokio для высокой скорости
✅ Чтение данных из файла для хеширования (реальный сценарий)
✅ Вывод хешей в виде Base64 и Hex ✅ Использует GPU (CUDA/OpenCL) для ускоренного хеширования через ocl
✅ Параллельно вычисляет хеши через rayon
✅ Работает с SHA-256, BLAKE3, FNV, xxHash
✅ Асинхронно загружает файлы через tokio Зачем Вам это уметь? : Для стандартных коллекций → DefaultHasher (SipHash). Для высокой скорости → twox-hash, fnv, blake3. Для безопасности → sha2, sha3, blake3. Для старых систем → md5 (не рекомендован). Для кастомных задач → своя реализация. Используется для хеширования значений в HashMap. use std::collections::hash_map::DefaultHasher; use std::hash::{Hash, Hasher}; fn main() { let mut hasher = DefaultHasher::new(); "hello".hash(&mut
Оглавление
ML на RUST без заморочек
Один Rust не п...Rust

Для чего нужна данная статья? :

Написать код который содержит:

Одновременное использование нескольких хеш-алгоритмов (SHA-256, BLAKE3, FNV, xxHash)
Генерацию HMAC (SHA-256) для безопасной аутентификации
Асинхронную обработку хеширования с tokio для высокой скорости
Чтение данных из файла для хеширования (реальный сценарий)
Вывод хешей в виде Base64 и Hex

Использует GPU (CUDA/OpenCL) для ускоренного хеширования через ocl
Параллельно вычисляет хеши через rayon
Работает с SHA-256, BLAKE3, FNV, xxHash
Асинхронно загружает файлы через tokio

Зачем Вам это уметь? :

Для стандартных коллекций → DefaultHasher (SipHash).

Для высокой скорости → twox-hash, fnv, blake3.

Для безопасности → sha2, sha3, blake3.

Для старых систем → md5 (не рекомендован).

Для кастомных задач → своя реализация.

1. Стандартные хеш-функции (std::collections::hash_map::DefaultHasher)

Используется для хеширования значений в HashMap.

use std::collections::hash_map::DefaultHasher;

use std::hash::{Hash, Hasher};

fn main() {

let mut hasher = DefaultHasher::new();

"hello".hash(&mut hasher);

println!("Hash: {}", hasher.finish());

}

🔹 Плюсы: Быстро, встроено в стандартную библиотеку.
🔹
Минусы: Не предназначено для криптографической безопасности.

2. Быстрые некриптографические хеш-функции (xxHash, FNV, SipHash)

Используются для хеш-таблиц и быстрых вычислений.

2.1 xxHash (twox-hash)

[dependencies]

twox-hash = "1.6"

use twox_hash::XxHash64;

use std::hash::{Hasher, Hash};

fn main() {

let mut hasher = XxHash64::default();

"hello".hash(&mut hasher);

println!("xxHash64: {}", hasher.finish());

}

🔹 Плюсы: Очень быстрый, отлично подходит для хеш-таблиц.
🔹
Минусы: Не криптостойкий.

2.2 FNV-1a (fnv)

[dependencies]

fnv = "1.0"

use fnv::FnvHasher;

use std::hash::{Hasher, Hash};

fn main() {

let mut hasher = FnvHasher::default();

"hello".hash(&mut hasher);

println!("Fnv Hash: {}", hasher.finish());

}

🔹 Плюсы: Быстрый, устойчивый к коллизиям.
🔹
Минусы: Не криптостойкий.

2.3 SipHash (стандартный, но медленный)

use std::collections::hash_map::RandomState;

use std::hash::{Hasher, Hash};

fn main() {

let state = RandomState::new();

let mut hasher = state.build_hasher();

"hello".hash(&mut hasher);

println!("SipHash: {}", hasher.finish());

}

🔹 Плюсы: Устойчив к атакам "расширения хеша".
🔹
Минусы: Медленнее xxHash и FNV.

3. Криптографические хеш-функции (SHA, BLAKE, MD5, Keccak)

Используются для безопасного хеширования.

3.1 SHA-2 (sha2)

[dependencies]

sha2 = "0.10"

use sha2::{Sha256, Digest};

fn main() {

let mut hasher = Sha256::new();

hasher.update(b"hello");

let result = hasher.finalize();

println!("SHA-256: {:?}", result);

}

🔹 Плюсы: Надёжность, стандарт безопасности.
🔹
Минусы: Медленнее, чем некриптографические хеши.

3.2 SHA-3 / Keccak (sha3)

[dependencies]

sha3 = "0.10"

use sha3::{Sha3_256, Digest};

fn main() {

let mut hasher = Sha3_256::new();

hasher.update(b"hello");

let result = hasher.finalize();

println!("SHA3-256: {:?}", result);

}

🔹 Плюсы: Надёжнее SHA-2, устойчив к атакам.
🔹
Минусы: Тяжелее в вычислениях.

3.3 BLAKE3 (быстрее SHA-3, аналог SHA-256)

[dependencies]

blake3 = "1.5"

use blake3::hash;

fn main() {

let result = hash(b"hello");

println!("BLAKE3: {:?}", result);

}

🔹 Плюсы: Очень быстрый, криптостойкий.
🔹
Минусы: Новый алгоритм, менее распространён.

3.4 MD5 (устаревший, но быстрый)

[dependencies]

md-5 = "0.10"

use md5::{Md5, Digest};

fn main() {

let mut hasher = Md5::new();

hasher.update(b"hello");

let result = hasher.finalize();

println!("MD5: {:?}", result);

}

🔹 Плюсы: Быстрый.
🔹
Минусы: Лёгкость подбора коллизий, не подходит для безопасности.

4. Кастомные хеш-функции

Можно создать свою хеш-функцию, например, XOR + модификация:

fn simple_hash(input: &str) -> u64 {

input.bytes().fold(0, |acc, x| acc.wrapping_mul(31).wrapping_add(x as u64))

}

fn main() {

println!("Custom hash: {}", simple_hash("hello"));

}

🔹 Плюсы: Гибкость, контроль над алгоритмом.
🔹
Минусы: Необходимо тестировать устойчивость.

Пример хеширования с GPU-ускорением (через OpenCL / CUDA) и параллельной обработкой (rayon).

✅ Использование GPU (OpenCL) через ocl
Мультипоточное хеширование через rayon
Одновременный запуск SHA-256, BLAKE3, xxHash, FNV
Чтение и обработка нескольких файлов
Параллельное вычисление через CPU + GPU

Cargo.toml

[dependencies]

tokio = { version = "1", features = ["full"] }

rayon = "1.7"

ocl = "0.19"

sha2 = "0.10"

blake3 = "1.5"

twox-hash = "1.6"

fnv = "1.0"

hex = "0.4"

OpenCL (GPU) код для SHA-256 (сохраните в sha256.cl)

__constant uint K[64] = {

0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,

0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,

0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,

0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,

0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,

0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,

0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,

0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,

0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,

0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,

0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,

0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,

0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,

0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,

0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,

0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2

};

__kernel void sha256(__global uchar* input, __global uint* output) {

int gid = get_global_id(0);

uint hash[8] = {

0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,

0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19

};

// Реализация SHA-256...

output[gid] = hash[0]; // Записываем результат

}

Rust-код с OpenCL и параллельным rayon

use ocl::{ProQue, Buffer};

use sha2::{Sha256, Digest};

use blake3::Hasher as Blake3Hasher;

use twox_hash::XxHash64;

use fnv::FnvHasher;

use std::hash::{Hash, Hasher};

use std::fs;

use std::time::Instant;

use rayon::prelude::*;

use hex::encode as hex_encode;

/// Функция для CPU-хеширования через SHA-256

fn hash_sha256(input: &[u8]) -> String {

let mut hasher = Sha256::new();

hasher.update(input);

hex_encode(hasher.finalize())

}

/// Функция для BLAKE3

fn hash_blake3(input: &[u8]) -> String {

let hasher = Blake3Hasher::new();

let result = hasher.update(input).finalize();

hex_encode(result.as_bytes())

}

/// Функция для FNV

fn hash_fnv(input: &[u8]) -> u64 {

let mut hasher = FnvHasher::default();

input.hash(&mut hasher);

hasher.finish()

}

/// Функция для xxHash

fn hash_xxhash(input: &[u8]) -> u64 {

let mut hasher = XxHash64::default();

input.hash(&mut hasher);

hasher.finish()

}

/// Хеширование на GPU через OpenCL

fn hash_sha256_gpu(input: &[u8]) -> Vec<u32> {

let kernel_src = fs::read_to_string("sha256.cl").expect("Ошибка чтения OpenCL файла");

let pro_que = ProQue::builder()

.src(kernel_src)

.dims(input.len())

.build().unwrap();

let buffer_input = Buffer::<u8>::builder()

.queue(pro_que.queue().clone())

.flags(ocl::flags::MEM_READ_ONLY)

.len(input.len())

.copy_host_slice(input)

.build().unwrap();

let buffer_output = Buffer::<u32>::builder()

.queue(pro_que.queue().clone())

.flags(ocl::flags::MEM_WRITE_ONLY)

.len(input.len())

.build().unwrap();

let kernel = pro_que.kernel_builder("sha256")

.arg(&buffer_input)

.arg(&buffer_output)

.build().unwrap();

unsafe { kernel.enq().unwrap(); }

let mut result = vec![0u32; input.len()];

buffer_output.read(&mut result).enq().unwrap();

result

}

/// Функция для параллельного хеширования

fn parallel_hashing(data: Vec<Vec<u8>>) {

let start = Instant::now();

let results: Vec<_> = data.par_iter().map(|input| {

let sha256 = hash_sha256(input);

let blake3 = hash_blake3(input);

let fnv = hash_fnv(input);

let xxhash = hash_xxhash(input);

let sha256_gpu = hash_sha256_gpu(input);

(sha256, blake3, fnv, xxhash, sha256_gpu)

}).collect();

for (i, res) in results.iter().enumerate() {

println!("🔹 Файл {}:", i + 1);

println!(" SHA-256: {}", res.0);

println!(" BLAKE3: {}", res.1);

println!(" FNV-1a: {}", res.2);

println!(" xxHash64: {}", res.3);

println!(" GPU SHA-256: {:?}", res.4);

}

println!("⏱ Время выполнения: {:?}", start.elapsed());

}

fn main() {

let file_data = vec![

fs::read("test1.txt").unwrap(),

fs::read("test2.txt").unwrap()

];

parallel_hashing(file_data);

}