saverioriotto.it

Progetto Pratico in Rust: Generatore di Password Sicure

Impara Rust creando un generatore di password sicure! Usa Cargo per creare un progetto reale, la libreria rand per generare password e gestisci i file per salvare le credenziali.

Progetto Pratico in Rust: Generatore di Password Sicure

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.

Configurazione del Progetto

Creare il Progetto con Cargo

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.

Aggiungere la Libreria rand

Modifica il file Cargo.toml per includere la libreria rand:

[dependencies]
rand = "0.8"

Quindi, esegui:

cargo build

Generare Password Casuali

Per generare password sicure, utilizzeremo i caratteri alfanumerici e simboli speciali.

Esempio di Generazione

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.

Salvare e Leggere Password

Salvare Password in un File

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);
    }
}

Leggere Password da un 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),
    }
}

Progetto Completo

Combiniamo tutto in un progetto completo con un'interfaccia utente semplice basata su CLI.

Codice Completo

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

Esercizi Pratici

  1. Aggiungi una Funzione di Crittografia
    Modifica il programma per criptare le password salvate usando la libreria aes.

  2. Genera Password Basate su Regole
    Permetti all'utente di scegliere tra password alfanumeriche e password con simboli speciali.

  3. Aggiungi un'Interfaccia Grafica
    Usa la libreria egui per trasformare il generatore in un'applicazione desktop.

Conclusione

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à!




Commenti
* Obbligatorio