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.
rand
Modifica 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à!