Windows Hello

Questo articolo descrive la nuova tecnologia Windows Hello inclusa nel sistema operativo Windows 10 e Windows 11 e descrive come gli sviluppatori possono implementare questa tecnologia per proteggere le app UWP (Universal Windows Platform) e i servizi back-end. Evidenzia le funzionalità specifiche di queste tecnologie che consentono di mitigare le minacce derivanti dall'uso di credenziali convenzionali e fornisce indicazioni su come progettare e distribuire queste tecnologie nell'ambito dell'implementazione di Windows 10 e Windows 11.

Questo articolo tratta in modo specifico lo sviluppo di app. Per informazioni sull'architettura e per dettagli sull'implementazione di Windows Hello, vedere la Guida di Windows Hello in TechNet.

Per un esempio di codice completo, vedere l'esempio di codice di Windows Hello in GitHub.

Per una procedura dettagliata sulla creazione di un'app UWP usando Windows Hello e sul servizio di autenticazione di supporto, vedere gli articoli sull'app per l'accesso a Windows Hello e sul servizio per l'accesso a Windows Hello.

1 Introduzione

Un presupposto fondamentale sulla sicurezza delle informazioni è la capacità di un sistema di identificare chi lo usa. Grazie all'identificazione di un utente, il sistema può decidere se l'utente viene identificato in modo appropriato (un processo noto come autenticazione) e che cosa può fare un utente autenticato (autorizzazione). La stragrande maggioranza dei sistemi informatici distribuiti in tutto il mondo dipende dalle credenziali utente per prendere decisioni di autenticazione e autorizzazione, il che significa che questi sistemi dipendono da password create dall'utente riutilizzabili come base per la loro sicurezza. La massima spesso citata secondo la quale l'autenticazione riguarda "qualcosa che si sa, qualcosa che si ha o qualcosa che si è" evidenzia chiaramente il problema: una password riutilizzabile è già un fattore di autenticazione, pertanto chiunque conosca la password può rappresentare l'utente proprietario.

1.1 Problemi con le credenziali tradizionali

Fin dalla metà degli anni sessanta, quando Fernando Corbató e il suo team presso il Massachusetts Institute of Technology hanno sostenuto l'introduzione delle password, utenti e amministratori hanno dovuto gestire l'uso delle password per l'autenticazione e l'autorizzazione degli utenti. Nel corso del tempo, l'archiviazione e l'uso delle password è in qualche modo progredito (con salting e hashing sicuro, ad esempio), ma devono ancora essere risolti due problemi. Le password sono facili da clonare e facili da sottrarre. Inoltre, gli errori di implementazione possono renderli non sicuri e gli utenti hanno difficoltà a bilanciare praticità e sicurezza.

1.1.1 Furto di credenziali

Il rischio più grande per le password è semplice: un utente malintenzionato può rubarle facilmente. Ogni posizione in cui si immette, elabora o archivia una password è vulnerabile. Ad esempio, un utente malintenzionato può rubare una raccolta di password o hash da un server di autenticazione intercettando il traffico di rete verso un server applicazioni, introducendo malware in un'applicazione o un dispositivo, registrando le sequenze di tasti dell'utente in un dispositivo o osservando i caratteri digitati. Questi sono solo i metodi di attacco più comuni.

Un altro rischio correlato è quello della riproduzione delle credenziali, in cui un utente malintenzionato acquisisce credenziali valide eseguendo intercettazioni su una rete non sicura e quindi riproducendole in un secondo momento per rappresentare un utente valido. La maggior parte dei protocolli di autenticazione (inclusi Kerberos e OAuth) protegge dagli attacchi di riproduzione includendo un timestamp nel processo di scambio delle credenziali, ma questa tattica protegge solo il token rilasciato dal sistema di autenticazione, non la password fornita dall'utente per ottenere il ticket.

1.1.2 Riutilizzo delle credenziali

L'approccio comune all'uso di un indirizzo e-mail come nome utente peggiora ulteriormente un problema già grave. Un utente malintenzionato che recupera una coppia nome utente-password da un sistema compromesso può provare la stessa coppia in altri sistemi. Questa tattica funziona spesso per consentire agli utenti malintenzionati di passare da un sistema compromesso ad altri sistemi. L'uso degli indirizzi e-mail come nomi utente comporta problemi aggiuntivi che verranno esaminati più avanti in questa guida.

1.2 Risoluzione dei problemi relativi alle credenziali

I problemi che le password rappresentano sono difficili da risolvere. L'uso di criteri password più stringenti non è sufficiente. Gli utenti possono semplicemente riciclare, condividere o annotare le password. Anche se la formazione degli utenti è fondamentale per la sicurezza dell'autenticazione, da sola la formazione non elimina il problema.

Windows Hello sostituisce le password con l'autenticazione a due fattori avanzata (2FA) verificando le credenziali esistenti e creando una credenziale specifica del dispositivo protetta da un movimento utente biometrico o basato su PIN. 

2 Che cos'è Windows Hello?

Windows Hello è il nome che Microsoft ha assegnato al nuovo sistema di accesso biometrico integrato in Windows 10 e Windows 11. Poiché è integrato direttamente nel sistema operativo, Windows Hello consente l'identificazione del volto o dell'impronta digitale per sbloccare i dispositivi degli utenti. L'autenticazione si verifica quando l'utente fornisce un identificatore biometrico univoco per accedere alle credenziali specifiche del dispositivo, il che significa che un utente malintenzionato che ruba il dispositivo può accedervi solo viene in possesso del PIN. L'archivio credenziali sicure di Windows protegge i dati biometrici nel dispositivo. Usando Windows Hello per sbloccare un dispositivo, l'utente autorizzato ottiene l'accesso a tutte le app, i dati, i siti Web, i servizi e le esperienze Windows.

L'autenticatore Windows Hello è noto come Hello. Hello è specifico della combinazione di un singolo dispositivo e di un utente specifico. Non esegue il roaming tra dispositivi, non è condiviso con un server o un'app chiamante e non può essere facilmente estratto da un dispositivo. Se più utenti condividono un dispositivo, ogni utente deve configurare il proprio account. Ogni account ottiene un Hello univoco per quel dispositivo. È possibile pensare a Hello come a un token che è possibile usare per sbloccare (o rilasciare) una credenziale archiviata. Hello da solo non esegue l'autenticazione a un'app o a un servizio, ma rilascia le credenziali relative. In altre parole, Hello non è una credenziale utente, ma è un secondo fattore per il processo di autenticazione.

2.1 Autenticazione di Windows Hello

Windows Hello offre a un dispositivo un modo affidabile per riconoscere un singolo utente, affrontando la prima parte del percorso tra un utente e un servizio o un elemento di dati richiesto. Dopo che il dispositivo ha riconosciuto l'utente, deve comunque autenticarlo prima di determinare se concedere l'accesso a una risorsa richiesta. Windows Hello fornisce un'autenticazione 2FA complessa completamente integrata in Windows e sostituisce le password riutilizzabili con la combinazione di un dispositivo specifico e di un movimento biometrico o basato su PIN.

Windows Hello non è solo un sostituto dei tradizionali sistemi 2FA. È concettualmente simile alle smart card: l'autenticazione viene eseguita tramite primitive crittografiche anziché confronti di stringhe e il materiale della chiave dell'utente è protetto all'interno di hardware a prova di manomissione. Windows Hello non richiede nemmeno i componenti infrastrutturali aggiuntivi necessari per la distribuzione delle smart card. In particolare, non è necessario disporre di un'infrastruttura a chiave pubblica (PKI) per gestire i certificati se al momento non è disponibile. Windows Hello combina i principali vantaggi delle smart card, ovvero flessibilità di distribuzione per le smart card virtuali e solida sicurezza per le smart card fisiche, senza nessuno dei relativi svantaggi.

2.2 Funzionamento di Windows Hello

Quando l'utente configura Windows Hello nel computer, genera una nuova coppia di chiavi pubblica e privata nel dispositivo. Il modulo TPM (Trusted Platform Module) genera e protegge questa chiave privata. Se il dispositivo non dispone di chip TPM, la chiave privata viene crittografata e protetta dal software. Inoltre, i dispositivi abilitati per TPM generano un blocco di dati che è possibile usare per attestare l'associazione di una chiave a TPM. Queste informazioni di attestazione possono essere usate nella soluzione per decidere se all'utente viene concesso un livello di autorizzazione diverso.

Per abilitare Windows Hello in un dispositivo, l'utente deve disporre di un account Azure Active Directory o di un account Microsoft connesso nelle impostazioni di Windows.

2.2.1 Protezione delle chiavi

Ogni volta che si genera materiale delle chiavi, è necessario proteggerlo dagli attacchi. Il modo più affidabile per eseguire questa operazione consiste nell'usare hardware specializzato. I moduli di protezione hardware sono usati da tempo per generare, archiviare ed elaborare le chiavi per le applicazioni critiche per la sicurezza. Le smart card sono un tipo speciale di modulo di protezione hardware, in quanto dispositivi conformi allo standard TPM (Trusted Computing Group). Ove possibile, l'implementazione di Windows Hello impiega l'hardware TPM integrato per generare, archiviare ed elaborare chiavi. Tuttavia, Windows Hello e Windows Hello for Work non richiedono un TPM integrato.

Ove possibile, Microsoft consiglia l'uso dell'hardware TPM. TPM protegge da un'ampia varietà di attacchi noti e potenziali, inclusi gli attacchi brute force basati su PIN. TPM offre anche un livello di protezione aggiuntivo dopo il blocco di un account. Quando TPM blocca il materiale della chiave, l'utente deve reimpostare il PIN. La reimpostazione del PIN comporta la rimozione di tutte le chiavi e dei certificati crittografati con il materiale della chiave precedente.

2.2.2 Autenticazione

Quando un utente vuole accedere al materiale della chiave protetto, il processo di autenticazione inizia quando l'utente immette un PIN o compie un movimento biometrico per sbloccare il dispositivo, un processo talvolta denominato "rilascio della chiave".

Un'applicazione non può mai usare le chiavi di un'altra applicazione, né può usare le chiavi di un altro utente. Queste chiavi vengono usate per firmare le richieste inviate al provider di identità (IDP), cercando l'accesso alle risorse specificate. Le applicazioni possono usare API specifiche per richiedere operazioni che richiedono materiale della chiave per azioni specifiche. L'accesso tramite queste API richiede la convalida esplicita tramite un movimento dell'utente e il materiale della chiave non è esposto all'applicazione richiedente. L'applicazione richiede un'azione specifica, ad esempio la firma di un elemento dati, e il livello di Windows Hello gestisce il lavoro effettivo e restituisce i risultati.

2.3 Operazioni preliminari all'implementazione di Windows Hello

Dopo aver acquisito una conoscenza di base del funzionamento di Windows Hello, è importante capire come implementarli nelle applicazioni.

Esistono diversi scenari che è possibile implementare con Windows Hello. Ad esempio, è sufficiente accedere all'app in un dispositivo. L'altro scenario comune consiste nell'eseguire l'autenticazione in un servizio. Anziché usare un nome di accesso e una password, si userà Windows Hello. I capitoli seguenti descrivono l'implementazione di un paio di scenari diversi, tra cui l'autenticazione nei servizi con Windows Hello e la conversione da un sistema di nome utente/password esistente a un sistema Windows Hello.

3 Implementazione di Windows Hello

Questo capitolo inizia con uno scenario greenfield privo di sistema di autenticazione, quindi spiega come implementare Windows Hello.

La sezione successiva spiega come eseguire la migrazione da un sistema di nome utente/password esistente. Tuttavia, anche se quel capitolo è interessante, potrebbe essere necessario esaminare questo per ottenere una conoscenza di base del processo e del codice necessario.

3.1 Registrazione di nuovi utenti

Si inizia con un nuovo servizio che userà Windows Hello e un nuovo utente ipotetico pronto per l'iscrizione su un nuovo dispositivo.

Il primo passaggio consiste nel verificare che l'utente sia in grado di usare Windows Hello. L'app verifica le impostazioni utente e le funzionalità del computer per assicurarsi che possa creare chiavi ID utente. Se l'app determina che l'utente non ha ancora abilitato Windows Hello, chiede all'utente di configurarlo prima di usare l'app.

Per abilitare Windows Hello, l'utente deve solo configurare un PIN nelle impostazioni di Windows, a meno che l'utente non lo configuri durante la Configurazione guidata.

Le righe di codice seguenti mostrano un modo semplice per verificare se l'utente è configurato per Windows Hello.

var keyCredentialAvailable = await KeyCredentialManager.IsSupportedAsync();
if (!keyCredentialAvailable)
{
    // User didn't set up PIN yet
    return;
}

Il passaggio successivo consiste nel chiedere all'utente le informazioni necessarie per iscriversi al servizio. È possibile chiedere all'utente il nome, il cognome, l'indirizzo e-mail e un nome utente univoco. È possibile usare l'indirizzo e-mail come identificatore univoco.

Questo scenario usa l'indirizzo e-mail come identificatore univoco per l'utente. Dopo l'iscrizione dell'utente, è consigliabile inviare un messaggio e-mail di convalida per assicurarsi che l'indirizzo sia valido. In questo modo, si ottiene un meccanismo per reimpostare l'account, se necessario.

Se l'utente ha impostato un PIN, l'app crea l'elemento KeyCredential dell'utente. L'app ottiene anche informazioni facoltative sull'attestazione della chiave per acquisire la prova crittografica che la chiave è stata generata in TPM. La chiave pubblica generata e, facoltativamente, l'attestazione, vengono inviate al server back-end per registrare il dispositivo in uso. Ogni coppia di chiavi generata in ogni dispositivo sarà univoca.

Il codice per creare l'elemento KeyCredential è simile al seguente:

var keyCreationResult = await KeyCredentialManager.RequestCreateAsync(
    AccountId, KeyCredentialCreationOption.ReplaceExisting);

L'elemento RequestCreateAsync è la parte che crea le chiavi pubblica e privata. Se il dispositivo dispone del chip TPM corretto, le API richiederanno al chip TPM di creare le chiavi privata e pubblica e di archiviare il risultato. Se non è disponibile alcun chip TPM, il sistema operativo creerà la coppia di chiavi nel codice. Non è possibile che l'app acceda direttamente alle chiavi private create. Parte della creazione delle coppie di chiavi è anche data dalle informazioni di attestazione risultanti. Per ulteriori informazioni sull'attestazione, vedere la sezione successiva.

Dopo aver creato le informazioni sulla coppia di chiavi e sull'attestazione nel dispositivo, la chiave pubblica, le informazioni di attestazione facoltative e l'identificatore univoco (ad esempio l'indirizzo e-mail) devono essere inviate al servizio di registrazione back-end e archiviate nel back-end.

Per consentire all'utente di accedere all'app in più dispositivi, il servizio back-end deve essere in grado di archiviare più chiavi per lo stesso utente. Poiché ogni chiave è univoca per ogni dispositivo, tutte queste chiavi connesse allo stesso utente verranno archiviate. Un identificatore di dispositivo viene usato per ottimizzare la parte server durante l'autenticazione degli utenti. Il capitolo successivo tratta nel dettaglio questo argomento.

Uno schema di database di esempio per archiviare queste informazioni nel back-end potrebbe essere simile al seguente:

Windows Hello sample database schema

La logica di registrazione potrebbe essere simile alla seguente:

Windows Hello registration logic

Le informazioni di registrazione raccolte potrebbero includere molte più informazioni di identificazione rispetto a quanto incluso in questo semplice scenario. Ad esempio, se l'app accede a un servizio protetto come quello bancario, dovrebbe essere necessario richiedere una prova di identità e altri elementi come parte del processo di iscrizione. Quando tutte le condizioni sono soddisfatte, la chiave pubblica di questo utente verrà archiviata nel back-end e usata per convalidare la prossima volta che l'utente userà il servizio.

using System;
using System.Runtime;
using System.Threading.Tasks;
using Windows.Storage.Streams;
using Windows.Security.Credentials;

static async void RegisterUser(string AccountId)
{
    var keyCredentialAvailable = await KeyCredentialManager.IsSupportedAsync();
    if (!keyCredentialAvailable)
    {
        // The user didn't set up a PIN yet
        return;
    }

    var keyCreationResult = await KeyCredentialManager.RequestCreateAsync(AccountId, KeyCredentialCreationOption.ReplaceExisting);
    if (keyCreationResult.Status == KeyCredentialStatus.Success)
    {
        var userKey = keyCreationResult.Credential;
        var publicKey = userKey.RetrievePublicKey();
        var keyAttestationResult = await userKey.GetAttestationAsync();
        IBuffer keyAttestation = null;
        IBuffer certificateChain = null;
        bool keyAttestationIncluded = false;
        bool keyAttestationCanBeRetrievedLater = false;

        keyAttestationResult = await userKey.GetAttestationAsync();
        KeyCredentialAttestationStatus keyAttestationRetryType = 0;

        if (keyAttestationResult.Status == KeyCredentialAttestationStatus.Success)
        {
            keyAttestationIncluded = true;
            keyAttestation = keyAttestationResult.AttestationBuffer;
            certificateChain = keyAttestationResult.CertificateChainBuffer;
        }
        else if (keyAttestationResult.Status == KeyCredentialAttestationStatus.TemporaryFailure)
        {
            keyAttestationRetryType = KeyCredentialAttestationStatus.TemporaryFailure;
            keyAttestationCanBeRetrievedLater = true;
        }
        else if (keyAttestationResult.Status == KeyCredentialAttestationStatus.NotSupported)
        {
            keyAttestationRetryType = KeyCredentialAttestationStatus.NotSupported;
            keyAttestationCanBeRetrievedLater = true;
        }
    }
    else if (keyCreationResult.Status == KeyCredentialStatus.UserCanceled ||
        keyCreationResult.Status == KeyCredentialStatus.UserPrefersPassword)
    {
        // Show error message to the user to get confirmation that user
        // does not want to enroll.
    }
}

3.1.1 Attestazione

Quando si crea la coppia di chiavi, è anche disponibile un'opzione per richiedere le informazioni di attestazione, generate dal chip TPM. Queste informazioni facoltative possono essere inviate al server come parte del processo di iscrizione. L'attestazione della chiave TPM è un protocollo che dimostra in modo crittografico che una chiave è associata a TPM. Questo tipo di attestazione può essere usato per garantire che si è verificata una determinata operazione di crittografia nel TPM di un determinato computer.

Quando riceve la chiave RSA generata, l'istruzione di attestazione e il certificato AIK, il server verifica le seguenti condizioni:

  • La firma del certificato AIK è valida.
  • Il certificato AIK si concatena a una radice attendibile.
  • Il certificato AIK e la relativa catena sono abilitati per l'OID EKU "2.23.133.8.3" (nome descrittivo "Attestation Identity Key Certificate").
  • Il certificato AIK è compreso in un intervallo di tempo valido.
  • Tutti i certificati CA emessi nella catena sono compresi in un intervallo di tempo valido e non sono revocati.
  • L'istruzione di attestazione è formata correttamente.
  • La firma sul BLOB KeyAttestation usa una chiave pubblica AIK.
  • La chiave pubblica inclusa nel BLOB KeyAttestation corrisponde alla chiave RSA pubblica inviata dal client insieme all'istruzione di attestazione.

L'app potrebbe assegnare all'utente un livello di autorizzazione diverso, a seconda di queste condizioni. Ad esempio, se uno di questi controlli ha esito negativo, potrebbe non registrare l'utente o limitare le operazioni che l'utente può eseguire.

3.2 Accesso con Windows Hello

Dopo essere stato registrato nel sistema, l'utente può usare l'app. A seconda dello scenario, è possibile chiedere agli utenti di eseguire l'autenticazione prima di iniziare a usare l'app o semplicemente chiedere loro di eseguire l'autenticazione quando iniziano a usare i servizi back-end.

3.3 Forzare l'accesso dell'utente

Per alcuni scenari, può essere necessario che l'utente dimostri che è la persona che ha eseguito l'accesso, prima di accedere all'app o a volte prima di eseguire una determinata azione all'interno dell'app. Ad esempio, prima che un'app bancaria invii il comando di trasferimento denaro al server, assicurarsi che sia l'utente, anziché qualcuno che ha trovato un dispositivo connesso, a tentare di eseguire una transazione. È possibile forzare l'accesso dell'utente nell'app usando la classe UserConsentVerifier. La riga di codice seguente forza l'utente a immettere le proprie credenziali.

La riga di codice seguente forza l'utente a immettere le proprie credenziali.

UserConsentVerificationResult consentResult = await UserConsentVerifier.RequestVerificationAsync("userMessage");
if (consentResult.Equals(UserConsentVerificationResult.Verified))
{
    // continue
}

Naturalmente, è anche possibile usare il meccanismo di risposta alla richiesta di verifica dal server, che richiede a un utente di immettere il codice PIN o le credenziali biometriche. Dipende dallo scenario che uno sviluppatore deve implementare. Questo meccanismo viene descritto nella sezione seguente.

3.4 Autenticazione nel back-end

Quando l'app tenta di accedere a un servizio back-end protetto, il servizio invia una richiesta di verifica all'app. L'app usa la chiave privata dell'utente per firmare la richiesta di verifica e la invia al server. Poiché il server ha archiviato la chiave pubblica per quell'utente, usa le API di crittografia standard per assicurarsi che il messaggio sia stato effettivamente firmato con la chiave privata corretta. Nel client la firma viene eseguita dalle API di Windows Hello. Lo sviluppatore non avrà mai accesso alla chiave privata di alcun utente.

Oltre a controllare le chiavi, il servizio può anche controllare l'attestazione della chiave e distinguere se sono state richiamate limitazioni sull'archiviazione delle chiavi nel dispositivo. Ad esempio, quando il dispositivo usa TPM per proteggere le chiavi, è più sicuro dei dispositivi che archiviano le chiavi senza TPM. La logica back-end potrebbe decidere, ad esempio, che l'utente può trasferire solo una determinata quantità di denaro quando non viene usato TPM per ridurre i rischi.

L'attestazione è disponibile solo per i dispositivi con un chip TPM versione 2.0 o successive. Pertanto, è necessario ricordarsi che queste informazioni potrebbero non essere disponibili in ogni dispositivo.

Il flusso di lavoro client potrebbe essere simile al grafico seguente:

Windows Hello client workflow

Quando l'app chiama il servizio nel back-end, il server invia una richiesta di verifica. La richiesta di verifica è firmata con il codice seguente:

var openKeyResult = await KeyCredentialManager.OpenAsync(AccountId);

if (openKeyResult.Status == KeyCredentialStatus.Success)
{
    var userKey = openKeyResult.Credential;
    var publicKey = userKey.RetrievePublicKey();
    var signResult = await userKey.RequestSignAsync(message);

    if (signResult.Status == KeyCredentialStatus.Success)
    {
        return signResult.Result;
    }
    else if (signResult.Status == KeyCredentialStatus.UserPrefersPassword)
    {

    }
}

La prima riga, KeyCredentialManager.OpenAsync, chiederà al sistema operativo di aprire l'handle di chiavi. Se l'operazione viene eseguita correttamente, è possibile firmare il messaggio di richiesta di verifica con il metodo KeyCredential.RequestSignAsync. Il sistema operativo richiede il PIN o i dati biometrici dell'utente attraverso Windows Hello. In nessun momento lo sviluppatore avrà accesso alla chiave privata dell'utente. La protezione viene mantenuta tramite le API.

Le API richiedono al sistema operativo di firmare la richiesta di verifica con la chiave privata. Il sistema chiede quindi all'utente di immettere un codice PIN o i dati biometrici configurati. Se le informazioni immesse sono corrette, il sistema può chiedere al chip TPM di eseguire le funzioni di crittografia e di firmare la richiesta. In alternativa, usare la soluzione software di fallback, se non è disponibile alcun TPM. Il client deve inviare la richiesta di verifica firmata al server.

In questo diagramma di sequenza viene illustrato un flusso di risposta alla richiesta di verifica di base:

Windows Hello challenge response

Il server deve convalidare la firma. Quando si richiede la chiave pubblica e la si invia al server per convalide future, si trova in un BLOB publicKeyInfo con codifica ASN.1. Se si esamina l'esempio di codice di Windows Hello in GitHub, si noterà che sono disponibili classi helper per eseguire il wrapping delle funzioni Crypt32 per convertire il BLOB con codifica ASN.1 in un BLOB CNG, di uso più comune. Il BLOB contiene l'algoritmo di chiave pubblica, ovvero RSA e la chiave pubblica RSA.

Nell'esempio il motivo per cui si converte il BLOB con codifica ASN.1 in un BLOB CNG è che può ò essere usato con CNG (/windows/desktop/SecCNG/cng-portal) e l'API BCrypt. Se si cerca il BLOB CNG, si viene diretti alla struttura BCRYPT_KEY_BLOB correlata. Questa superficie API può essere usata per l'autenticazione e la crittografia nelle applicazioni Windows. ASN.1 è uno standard documentato per la comunicazione delle strutture di dati che è possibile serializzare ed è comunemente usato nella crittografia a chiave pubblica e con i certificati. Ecco perché le informazioni sulla chiave pubblica vengono restituite in questo modo. La chiave pubblica è una chiave RSA e questo è l'algoritmo che Windows Hello usa quando firma i dati.

Dopo aver ottenuto il BLOB CNG, è necessario convalidare la richiesta di verifica firmata rispetto alla chiave pubblica dell'utente. Poiché tutti usano la propria tecnologia di sistema o back-end, non esiste un modo generico per implementare questa logica. Si usa SHA256 come algoritmo hash e Pkcs1 per SignaturePadding, pertanto assicurarsi di usarlo per convalidare la risposta firmata dal client. Anche in questo caso, fare riferimento all'esempio di come eseguire questa operazione nel server in .NET 4.6, ma in generale avrà un aspetto simile al seguente:

using (RSACng pubKey = new RSACng(publicKey))
{
    retval = pubKey.VerifyData(originalChallenge, responseSignature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
}

È stata letta la chiave pubblica archiviata, ovvero una chiave RSA. Si convalida il messaggio di richiesta di verifica firmato con la chiave pubblica e, se l'operazione ha esito positivo, l'utente viene autorizzato. Se l'utente viene autenticato, l'app può chiamare i servizi back-end come di consueto.

Il codice completo potrebbe essere simile al seguente:

using System;
using System.Runtime;
using System.Threading.Tasks;
using Windows.Storage.Streams;
using Windows.Security.Cryptography;
using Windows.Security.Cryptography.Core;
using Windows.Security.Credentials;

static async Task<IBuffer> GetAuthenticationMessageAsync(IBuffer message, String AccountId)
{
    var openKeyResult = await KeyCredentialManager.OpenAsync(AccountId);

    if (openKeyResult.Status == KeyCredentialStatus.Success)
    {
        var userKey = openKeyResult.Credential;
        var publicKey = userKey.RetrievePublicKey();
        var signResult = await userKey.RequestSignAsync(message);
        if (signResult.Status == KeyCredentialStatus.Success)
        {
            return signResult.Result;
        }
        else if (signResult.Status == KeyCredentialStatus.UserCanceled)
        {
            // Launch app-specific flow to handle the scenario 
            return null;
        }
    }
    else if (openKeyResult.Status == KeyCredentialStatus.NotFound)
    {
        // PIN reset has occurred somewhere else and key is lost.
        // Repeat key registration
        return null;
    }
    else
    {
        // Show custom UI because unknown error has happened.
        return null;
    }
}

L'implementazione del meccanismo di verifica-risposta corretto non rientra nell'ambito di questo documento, ma questo argomento richiede attenzione per creare correttamente un meccanismo sicuro per evitare attacchi di tipo replay o man-in-the-middle.

3.5 Registrazione di un altro dispositivo

Oggi, è comune che gli utenti abbiano più dispositivi con le stesse app installate. Cosa accade quando si usa Windows Hello con più dispositivi?

Quando si usa Windows Hello ogni dispositivo verrà creato un set univoco di chiavi private e pubbliche. Ciò significa che se si vuole che un utente usi più dispositivi, il back-end deve essere in grado di archiviare più chiavi pubbliche da questo utente. Per un esempio della struttura di tabella, vedere il diagramma di database nella Sezione 2.1.

La registrazione di un altro dispositivo è quasi identica alla registrazione di un utente per la prima volta. È comunque necessario assicurarsi che l'utente che esegue la registrazione di questo nuovo dispositivo sia effettivamente l'utente che dichiara di essere. A tale scopo, usare qualsiasi meccanismo di autenticazione a due fattori usato oggi. Sono disponibili diversi modi per eseguire questa operazione in modo sicuro. Dipende dallo scenario.

Ad esempio, se si usa ancora il nome di accesso e la password, è possibile usarli per autenticare l'utente e chiedere loro di usare uno dei metodi di verifica come SMS o e-mail. Se non si dispone di un nome di accesso e di una password, è anche possibile usare uno dei dispositivi già registrati per inviare una notifica all'app nel dispositivo. L'app di autenticazione MSA ne è un esempio. In breve, è consigliabile usare un meccanismo 2FA comune per registrare dispositivi aggiuntivi per l'utente.

Il codice per registrare il nuovo dispositivo equivale esattamente alla registrazione dell'utente per la prima volta (dall'interno dell'app).

var keyCreationResult = await KeyCredentialManager.RequestCreateAsync(
    AccountId, KeyCredentialCreationOption.ReplaceExisting);

Per semplificare il riconoscimento dei dispositivi registrati da parte dell'utente, è possibile scegliere di inviare il nome del dispositivo o un altro identificatore come parte della registrazione. È utile, ad esempio, se si vuole implementare un servizio nel back-end in cui gli utenti possono annullare la registrazione dei dispositivi quando si smarrisce un dispositivo.

3.6 Uso di più account nell'app

Oltre a supportare più dispositivi per un singolo account, è comune supportare più account in una singola app. È ad esempio possibile connettersi a più account X dall'interno dell'app. Con Windows Hello è possibile creare più coppie di chiavi e supportare più account all'interno dell'app.

Un modo per eseguire questa operazione consiste nel mantenere il nome utente o l'identificatore univoco descritto nel capitolo precedente nello spazio di memorizzazione isolato. Pertanto, ogni volta che si crea un nuovo account, si archivia l'ID account nello spazio di memorizzazione isolato.

Nell'interfaccia utente dell'app è possibile consentire all'utente di scegliere uno degli account creati in precedenza o di iscriversi con un nuovo account. Il flusso di creazione di un nuovo account è identico a quello descritto in precedenza. La scelta di un account implica un elenco degli account archiviati sullo schermo. Dopo aver selezionato un account, usare l'ID account per accedere all'utente nell'app:

var openKeyResult = await KeyCredentialManager.OpenAsync(AccountId);

Il resto del flusso è uguale a quello descritto in precedenza. Per maggiore chiarezza, tutti questi account sono protetti dallo stesso PIN o dallo stesso movimento biometrico perché in questo scenario vengono usati in un singolo dispositivo con lo stesso account di Windows.

4 Migrazione di un sistema esistente a Windows Hello

Questa breve sezione descrive un'app UWP (Universal Windows Platform) con sistema back-end che usa un database per archiviare il nome utente e la password con hash. Queste app raccolgono le credenziali dall'utente all'avvio dell'app e le usano quando il sistema back-end restituisce la richiesta di autenticazione.

Si descriveranno le parti da modificare o sostituire per consentire il funzionamento di Windows Hello.

Si è già descritta la maggior parte delle tecniche nei capitoli precedenti. L'aggiunta di Windows Hello al sistema esistente comporta l'aggiunta di un paio di flussi diversi nella parte registrazione e autenticazione del codice.

Un approccio consiste nel consentire all'utente di scegliere quando eseguire l'aggiornamento. Dopo che l'utente ha effettuato l'accesso all'app e rilevato che l'app e il sistema operativo sono in grado di supportare Windows Hello, è possibile chiedere all'utente se vuole aggiornare le credenziali per usare questo sistema moderno e più sicuro. È possibile usare il codice seguente per verificare se l'utente è in grado di usare Windows Hello.

var keyCredentialAvailable = await KeyCredentialManager.IsSupportedAsync();

L'interfaccia utente potrebbe essere simile alla seguente:

Windows Hello ui

Se l'utente sceglie di iniziare a usare Windows Hello, creare l'elemento KeyCredential descritto in precedenza. Il server di registrazione back-end aggiunge la chiave pubblica e l'istruzione di attestazione facoltativa al database. Poiché l'utente è già autenticato con nome utente e password, il server può collegare le nuove credenziali alle informazioni utente correnti nel database. Il modello di database potrebbe essere uguale all'esempio descritto in precedenza.

Se l'app ha creato l'elemento KeyCredential per gli utenti, archivia l'ID utente nello spazio di memorizzazione isolato in modo che l'utente possa scegliere questo account dall'elenco al successivo avvio dell'app. Da questo punto in poi, il flusso segue esattamente gli esempi descritti nei capitoli precedenti.

Il passaggio finale della migrazione a uno scenario completo di Windows Hello consiste nel disabilitare l'opzione nome e password di accesso nell'app e nel rimuovere le password con hash archiviate dal database.

5 Riepilogo

Windows 10 e Windows 11 introducono un livello di sicurezza superiore, ma semplice da attuare. Windows Hello fornisce un nuovo sistema di accesso biometrico che riconosce l'utente e vanifica attivamente i tentativi di eludere la corretta identificazione. Può anche fornire più livelli di chiavi e certificati che non possono mai essere rivelati o usati all'esterno del modulo TPM. È inoltre disponibile un ulteriore livello di sicurezza attraverso l'uso opzionale di certificati e chiavi di identità di attestazione.

Gli sviluppatori possono usare queste linee guida per la progettazione e la distribuzione di queste tecnologie per aggiungere facilmente l'autenticazione sicura alle implementazioni di Windows 10 e Windows 11 per proteggere app e servizi back-end. Il codice necessario è minimo e facile da comprendere. Windows 10 e Windows 11 gestiscono la maggior parte del carico.

Grazie alle opzioni di implementazione flessibili, Windows Hello può sostituire il sistema di autenticazione esistente o lavorare al suo fianco. L'esperienza di distribuzione è indolore ed economica. Non è necessaria alcuna infrastruttura aggiuntiva per distribuire la sicurezza di Windows 10 e Windows 11. Con Windows Hello integrato, i sistemi operativi Windows 10 e Windows 11 offrono la soluzione più sicura ai problemi di autenticazione riscontrati dallo sviluppatore moderno.

Missione compiuta. Ora Internet è un posto più sicuro.

6 Risorse

6.1 Articoli e codice di esempio

6.2 Terminologia

Termine Definizione
AIK Una chiave di identità di attestazione rappresenta una prova crittografica (attestazione chiave TPM) firmando le proprietà della chiave non migrabile e fornendo le proprietà e la firma alla relying party per la verifica. La firma risultante è denominata "istruzione di attestazione". Poiché la firma viene creata usando la chiave privata AIK, che può essere usata solo nel TPM che l'ha creata, la relying party ha la sicurezza che la chiave attestata sia veramente non migrabile e che non possa essere usata all'esterno di tale TPM.
Certificato AIK Un certificato AIK viene usato per attestare la presenza di un AIK all'interno di un TPM. Consente anche di attestare che altre chiavi certificate dall'AIK provengono da quel particolare TPM.
IDP Un IDP è un provider di identità. Un esempio è la build IDP di Microsoft per gli account Microsoft. Ogni volta che un'applicazione deve eseguire l'autenticazione con un account MSA, può chiamare l'IDP MSA.
PKI L'infrastruttura a chiave pubblica viene comunemente usata per puntare a un ambiente ospitato da un'organizzazione e responsabile della creazione e della revoca di chiavi e così via.
TPM Il modulo TPM può essere usato per creare coppie di chiavi pubbliche/private crittografiche in modo che la chiave privata non possa mai essere rivelata o usata all'esterno del TPM (chiave non migrabile).
Attestazione della chiave TPM Protocollo che dimostra in modo crittografico che una chiave è associata al modulo TPM. Questo tipo di attestazione può essere usato per garantire che si è verificata una determinata operazione di crittografia nel TPM di un determinato computer