Для чего нужна данная статья? :
Написать код который содержит:
✅ Одновременное использование нескольких хеш-алгоритмов (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);
}