Crittografare dati sensibili in ASP.NET Core per supportare GDPR

di Marco De Sanctis, in ASP.NET Core,

Quando si memorizzano dati sensibili dei nostri utenti, per esempio numeri di carte di credito, dobbiamo assolutamente prendere tutte le precauzioni necessarie per evitare leak di queste informazioni, anche in caso di data breach: in parole povere, anche se un utente malintenzionato riuscisse ad avere accesso al nostro database, questi dati non devono essere consumabili e comprensibili. Al di là di una buona etica professionale, inoltre, con l'avvento di GDPR questo diventa un vero e proprio requisito legale.

Fortunatemente ASP.NET Core espone una serie di API per la protezione dei dati che rendono operazioni quali encryption e hashing estremamente semplici: stiamo parlando delle Data Protection API.

Immaginiamo, per esempio, di avere una form di input dei dati cliente, e che tra questi sia contenuto un numero di carta di credito. Ovviamente non vogliamo memorizzarlo in chiaro nel database, e pertanto vogliamo criptarlo prima del salvataggio. Per farlo, dobbiamo prima di tutto creare un IDataProtector nel nostro controller:

private IDataProtector _protector;

public CustomerController(IDataProtectionProvider provider)
{
    _protector = provider.CreateProtector("Customer.Data");
}

Questo oggetto non può essere istanziato direttamente, ma richiede un IDataProtectionProvider che, comunque, è già per default configurato come servizio nel motore di DependencyInjection di ASP.NET Core - questo perchè è utilizzato per diversi altri scopi, tra cui AntiForgeryToken e cookie di autenticazione. Da questo nostro provider, possiamo costruire un protector tramite il metodo CreateProtector, a cui dobbiamo passare quella che nella documentazione è chiamata una Purpose String. Si tratta fondamentalmente di una stringa che viene utilizzata (in concomitanza con altri dati) per generare la chiave di cifratura.

Un protector con una differente Purpose String non sarà in grado di decodificare quanto generato da quello del codice in alto: questo accorgimento aggiunge un ulteriore layer di protezione alla nostra applicazione, perchè se differenti moduli usano diverse chiavi, il rischio di leak di dati nel caso di un bug di sicurezza in uno di questi sarà circoscritto ai suoi dati.

Una volta ottenuto questo protector, possiamo usarlo per crittografare il numero di carta di credito, prima di salvarlo su database, semplicemente invocando il metodo Protect:

public ActionResult Create(Customer customer)
{
    try
    {
        customer.CreditCard =
            _protector.Protect(customer.CreditCard);

        _customerRepository.Save(customer);

        return RedirectToAction(nameof(Index));
    }
    catch
    {
        return View();
    }
}

Quando poi dobbiamo visualizzare il customer, se vogliamo decriptare il dato possiamo utilizzare la stessa classe Protector e il metodo Unprotect:

public ActionResult Details(int id)
{
    Customer customer = _customerRepository.GetCustomerById();

    customer.CreditCard = _protector.Unprotect(customer.CreditCard);

    return View();
}

Le chiavi di crittografia utilizzate da Data Protection API vengono normalmente generate sulla singola macchina. In condizioni di server farm o quando vanno condivise tra più applicazioni, possiamo condividere le chiavi con le stesse tecniche che abbiamo illustrato nei precedenti script (https://www.aspitalia.com/script/1282/Usare-AntiForgeryToken-Scenario-Web-Farm-ASP.NET-Core-MVC.aspx e https://www.aspitalia.com/script/1283/Sfruttare-Redis-Storage-AntiForgeryToken-ASP.NET-Core.aspx).

Commenti

Visualizza/aggiungi commenti

| Condividi su: Twitter, Facebook, LinkedIn

Per inserire un commento, devi avere un account.

Fai il login e torna a questa pagina, oppure registrati alla nostra community.

Approfondimenti

I più letti di oggi