Dopo aver esplorato i concetti fondamentali di Rust, è il momento di metterli in pratica! In questo articolo, costruiremo un generatore di password sicure. Utilizzeremo Cargo per gestire il progetto, la libreria rand per generare password casuali e lavoreremo con i file per salvare e recuperare le password.
Cargo è lo strumento di build e gestione delle dipendenze di Rust. Per iniziare, crea un nuovo progetto:
cargo new password_generator
cd password_generator
All'interno della directory del progetto, troverai due file principali: src/main.rs per il codice e Cargo.toml per le dipendenze.
randModifica il file Cargo.toml per includere la libreria rand:
[dependencies]
rand = "0.8"
Quindi, esegui:
cargo build
Per generare password sicure, utilizzeremo i caratteri alfanumerici e simboli speciali.
Ecco un esempio di codice per generare una password casuale:
use rand::{distributions::Uniform, Rng};
fn genera_password(lunghezza: usize) -> String {
let chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~";
rand::thread_rng()
.sample_iter(&Uniform::new_inclusive(0, chars.len() - 1))
.take(lunghezza)
.map(|i| chars.chars().nth(i).unwrap())
.collect()
}
fn main() {
let password = genera_password(12);
println!("Password generata: {}", password);
}
Spiegazione:
rand::thread_rng(): Crea un generatore di numeri casuali basato sul thread corrente.Uniform: per scegliere casualmente un indice tra quelli presenti nei caratteri disponibili (chars), ho usato una distribuzione uniforme..take(lunghezza): Limita il numero di caratteri..collect(): Converte i caratteri in una stringa.Per salvare una password, puoi usare il modulo std::fs.
use std::fs::{self, OpenOptions};
use std::io::{self, Write};
fn salva_password(file: &str, password: &str) -> std::io::Result<()> {
let mut file = OpenOptions::new()
.create(true) // Se il file non esiste, lo crea
.append(true) // Aggiunge i dati al file esistente
.open(file)?;
writeln!(file, "{}", password)
}
fn main() {
let password = genera_password(12);
let file = "passwords.txt";
if let Err(e) = salva_password(file, &password) {
eprintln!("Errore nel salvataggio: {}", e);
} else {
println!("Password salvata in {}", file);
}
}
Per recuperare una password salvata:
fn leggi_password(file: &str) -> std::io::Result {
fs::read_to_string(file)
}
fn main() {
let file = "passwords.txt";
match leggi_password(file) {
Ok(contenuto) => println!("Password salvate:\n{}", contenuto),
Err(e) => eprintln!("Errore nella lettura: {}", e),
}
}
Combiniamo tutto in un progetto completo con un'interfaccia utente semplice basata su CLI.
use rand::{distributions::Uniform, Rng};
use std::fs::{self, OpenOptions};
use std::io::{self, Write};
fn genera_password(lunghezza: usize) -> String {
let chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~";
rand::thread_rng()
.sample_iter(&Uniform::new_inclusive(0, chars.len() - 1))
.take(lunghezza)
.map(|i| chars.chars().nth(i).unwrap())
.collect()
}
fn salva_password(file: &str, password: &str) -> std::io::Result<()> {
let mut file = OpenOptions::new()
.create(true) // Se il file non esiste, lo crea
.append(true) // Aggiunge i dati al file esistente
.open(file)?;
writeln!(file, "{}", password)
}
fn leggi_password(file: &str) -> std::io::Result {
fs::read_to_string(file)
}
fn main() {
let file = "passwords.txt";
loop {
println!("Generatore di Password Sicure");
println!("1. Genera una nuova password");
println!("2. Leggi password salvate");
println!("3. Esci");
println!("Scegli un'opzione:");
let mut scelta = String::new();
io::stdin().read_line(&mut scelta).unwrap();
match scelta.trim() {
"1" => {
println!("Inserisci la lunghezza della password:");
let mut lunghezza = String::new();
io::stdin().read_line(&mut lunghezza).unwrap();
if let Ok(lunghezza) = lunghezza.trim().parse::() {
let password = genera_password(lunghezza);
println!("Password generata: {}", password);
if let Err(e) = salva_password(file, &password) {
eprintln!("Errore nel salvataggio: {}", e);
} else {
println!("Password salvata in {}", file);
}
} else {
println!("Lunghezza non valida.");
}
}
"2" => match leggi_password(file) {
Ok(contenuto) => println!("Password salvate:\n{}", contenuto),
Err(e) => eprintln!("Errore nella lettura: {}", e),
},
"3" => break,
_ => println!("Opzione non valida."),
}
}
}
Il progetto completo lo trovi su Github
Aggiungi una Funzione di Crittografia
Modifica il programma per criptare le password salvate usando la libreria aes.
Genera Password Basate su Regole
Permetti all'utente di scegliere tra password alfanumeriche e password con simboli speciali.
Aggiungi un'Interfaccia Grafica
Usa la libreria egui per trasformare il generatore in un'applicazione desktop.
Questo progetto pratico mostra come utilizzare Rust per creare applicazioni sicure e funzionali. Hai imparato a gestire un progetto con Cargo, utilizzare librerie esterne e lavorare con i file. Prova a estendere il generatore con nuove funzionalità per mettere alla prova le tue abilità!