Rust中的密码学:使用ring和sha2库进行加密和哈希

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

Rust中的密码学:使用ring和sha2库进行加密和哈希



Rust是一种系统编程语言,保证内存安全和高性能。凭借这些特性,它非常适合密码学任务。在本文中,我们将介绍两个流行的库:ring(用于对称加密和哈希)和sha2(用于纯哈希)。您将学习如何使用AES-GCM加密数据、计算SHA-256哈希以及创建HMAC签名。



为什么选择Rust进行密码学?

Rust在编译阶段消除了整类漏洞(缓冲区溢出、数据竞争)。像ring这样的Rust密码学库使用汇编和C语言编写,并带有安全封装,从而提供与C相当的速度,同时具备Rust的可靠性。



项目设置

创建一个新项目并在Cargo.toml中添加依赖项:

[dependencies]ring = "0.17"sha2 = "0.10"hex = "0.4"  # 用于方便地显示字节


对称加密:使用ring的AES-GCM

AES-GCM(伽罗瓦/计数器模式)是一种现代对称加密标准,既提供机密性,也提供认证(完整性检查)。ring库提供了简单且安全的API。



数据加密

加密需要:密钥(256位)、nonce(96位)和明文。每个使用同一密钥的加密操作必须使用唯一的nonce。

use ring::aead::{Aad, LessSafeKey, Nonce, UnboundKey, AES_256_GCM};use ring::rand::{SecureRandom, SystemRandom};

fn encrypt_aes_gcm(key: &[u8; 32], plaintext: &[u8]) -> Vec<u8> { let rng = SystemRandom::new(); let unbound_key = UnboundKey::new(&AES_256_GCM, key).unwrap(); let key = LessSafeKey::new(unbound_key);

// 生成随机nonce let mut nonce_bytes = [0u8; 12]; rng.fill(&mut nonce_bytes).unwrap(); let nonce = Nonce::assume_unique_for_key(nonce_bytes);

// 使用空附加数据(AAD)进行加密 let mut in_out = plaintext.to_vec(); let tag = key.seal_in_place_separate_tag(nonce, Aad::empty(), &mut in_out).unwrap(); // 返回nonce + 加密数据 + 认证标签 let mut result = nonce_bytes.to_vec(); result.extend_from_slice(&in_out); result.extend_from_slice(tag.as_ref()); result}


解密

解密时,提取nonce、标签和密文,然后调用open_in_place。

fn decrypt_aes_gcm(key: &[u8; 32], ciphertext: &[u8]) -> Option<Vec<u8>> {    if ciphertext.len() < 28 { return None; } // 至少12(nonce)+ 16(标签)

let (nonce_bytes, rest) = ciphertext.split_at(12); let (encrypted, tag_bytes) = rest.split_at(rest.len() - 16); let nonce = Nonce::assume_unique_for_key(*nonce_bytes); let unbound_key = UnboundKey::new(&AES_256_GCM, key).unwrap(); let key = LessSafeKey::new(unbound_key);

let mut in_out = encrypted.to_vec(); in_out.extend_from_slice(tag_bytes); // ring期望标签在末尾 match key.open_in_place(nonce, Aad::empty(), &mut in_out) { Ok(plaintext) => { let plain_len = plaintext.len(); Some(plaintext[..plain_len].to_vec()) }, Err(_) => None // 密钥错误或数据损坏 }}


使用示例

fn main() {    let key = b"0123456789abcdef0123456789abcdef"; // 32字节    let data = b"给Rust的秘密消息!";        let encrypted = encrypt_aes_gcm(key, data);    println!("加密后(hex):{}", hex::encode(&encrypted));        if let Some(decrypted) = decrypt_aes_gcm(key, &encrypted) {        println!("解密后:{}", String::from_utf8(decrypted).unwrap())                    

推荐