Criptografía en Rust: cifrado y hash con ring y sha2

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Criptografía en Rust: cifrado y hash con las bibliotecas ring y sha2



Rust es un lenguaje de programación de sistemas que proporciona seguridad de memoria y rendimiento comparable a C/C++. Gracias a su estricto sistema de tipos y modelo de propiedad, Rust es ideal para implementar algoritmos criptográficos, donde los errores pueden provocar vulnerabilidades graves. En este artículo, veremos cómo usar las bibliotecas populares ring y sha2 para realizar operaciones criptográficas básicas: cifrado simétrico, hash y cálculo de HMAC.



Biblioteca ring: herramienta universal para criptografía



La biblioteca ring es una de las bibliotecas criptográficas más populares para Rust. Proporciona implementaciones seguras de muchos algoritmos, incluyendo AES-GCM para cifrado, SHA-256 para hash y HMAC para autenticación de mensajes. ring está escrita en Rust y C, lo que garantiza alto rendimiento y seguridad.



Para empezar, agregue la dependencia en su Cargo.toml:



[dependencies]ring = "0.17"


Cifrado simétrico con AES-GCM



AES-GCM (Galois/Counter Mode) es un modo de cifrado que proporciona tanto confidencialidad como autenticación de datos. Se usa ampliamente en protocolos modernos como TLS.



Ejemplo de cifrado y descifrado de una cadena con ring:



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

fn encrypt(plaintext: &[u8], key: &[u8; 32]) -> Result<Vec<u8>, Unspecified> { let rng = SystemRandom::new(); let unbound_key = UnboundKey::new(&AES_256_GCM, key)?; let key = LessSafeKey::new(unbound_key);

// Generación de nonce aleatorio (12 bytes) let mut nonce_bytes = [0u8; 12]; rng.fill(&mut nonce_bytes)?; let nonce = Nonce::assume_unique_for_key(nonce_bytes);

// Buffer para datos cifrados + etiqueta de autenticación let mut in_out = plaintext.to_vec(); key.seal_in_place_append_tag(nonce, Aad::empty(), &mut in_out)?;

// Devolvemos nonce + datos cifrados let mut result = nonce_bytes.to_vec(); result.extend_from_slice(&in_out); Ok(result)}

fn decrypt(ciphertext: &[u8], key: &[u8; 32]) -> Result<Vec<u8>, Unspecified> { let unbound_key = UnboundKey::new(&AES_256_GCM, key)?; let key = LessSafeKey::new(unbound_key);

// Extraemos nonce (primeros 12 bytes) let (nonce_bytes, encrypted) = ciphertext.split_at(12); let nonce = Nonce::assume_unique_for_key(nonce_bytes.try_into().unwrap());

let mut in_out = encrypted.to_vec(); let plaintext = key.open_in_place(nonce, Aad::empty(), &mut in_out)?; Ok(plaintext.to_vec())}

fn main() { let key = b"01234567890123456789012345678901"; // 32 bytes para AES-256 let data = b"Mensaje secreto";

let encrypted = encrypt(data, key).unwrap(); println!("Cifrado: {:?}", encrypted);

let decrypted = decrypt(&encrypted, key).unwrap(); println!("Descifrado: {}", String::from_utf8(decrypted).unwrap());}


Este código demuestra el ciclo completo de cifrado: generación de nonce aleatorio, cifrado con etiqueta de autenticación y posterior descifrado. Tenga en cuenta que el nonce debe ser único para cada cifrado con la misma clave.



Hash con la biblioteca sha2



La biblioteca sha2 proporciona implementaciones de los algoritmos de la familia SHA-2, incluyendo SHA-256, SHA-384 y SHA-512. El hash se utiliza para verificar la integridad de datos, almacenar contraseñas y crear firmas digitales.



Agregue la dependencia:



[dependencies]sha2 = "0.10"


Ejemplo de hash de una cadena con SHA-256:



use sha2:                    

Recommendations