Un sistema di licenze sicure

8

Quindi sto cercando di pensare a un buon modo per verificare se il codice di licenza che un utente fornisce per un programma è legittimo o meno.

Supponiamo che questo sia il modo in cui ottengono la licenza

  1. Fanno un qualche tipo di acquisto.
  2. Un server genera una licenza in base al nome utente
  3. Server dà licenza all'utente
  4. Quando l'utente tenta di utilizzare il programma per la prima volta, utilizza il suddetto codice di licenza
  5. Il server controlla se la licenza è legittima.

Le parti di cui ho una domanda sono l'ottimo modo per generare una licenza "sicura" con un solo nome utente.

Attualmente ho qualcosa di simile a questo su un server Java.

username += "a long random string literal here";
        username = username.toUpperCase();
        md = MessageDigest.getInstance("SHA-256");
           md.update(username.getBytes());
            byte[] mdbytes = md.digest();

Quindi, come puoi vedere, aggiungo una stringa lunga e casuale al nome utente, quindi rendendolo insensibile alle maiuscole cambiandolo in maiuscolo.

Sto utilizzando SHA sul nome utente modificato.

Quindi quali sono esattamente i punti deboli in questo? Il loro è un modo migliore per controllare le licenze?

Ovviamente il client non vedrebbe mai il metodo di generazione, quindi non vedo come potrebbero generare le proprie licenze a meno che non abbiano ottenuto la stringa che sto aggiungendo al nome utente.

    
posta Austin 24.10.2012 - 10:55
fonte

3 risposte

20

Il metodo di licenza generazione non è davvero così importante, purché non sia banale. Il trucco è come il tuo cliente verifica che la licenza sia corretta.

Diciamo che fai qualcosa del genere:

BOOL verifyLicense (char* licenseKey)
{
    BOOL result = false;

    if(strlen(licenseKey) > 128)
        return false;

    char* url = (char*)malloc(1024);
    sprintf(url, "%s%s", LicenseServerBaseURL, licenseKey);

    char* response = http_get(url);

    if (strcmp(response, "OK") == 0)
        result = true;

    free(result);
    free(url);
}

Questo è piuttosto semplice: eseguiamo alcuni controlli di base sulla chiave di licenza, creiamo un URL che contiene la chiave di licenza, quindi eseguiamo un HTTP GET sul server per controllare la licenza. Se restituisce "OK", lo accettiamo.

Il problema con questo è che chiunque può disassemblare il client:

 ...
 push 06f2011c        ; address of url string
 call http_get        ; http_get(url)
 mov ebx, eax         ; store a copy of the result address
 push 04830040        ; ASCII "OK"
 push eax             ; address of response string
 call msvcrt.strcmp   ; strcmp(response, "OK")
 test eax, eax        ; if( ^ == 0 )
 jnz exit             ; skip if branch if non-zero
 mov eax, 1           ; result = true
exit:
 push ebx
 call msvcrt.free     ; free(result)
 push 06f2011c
 call msvcrt.free     ; free(url)
 ret

Tutto quello che devo fare è modificare jnz exit in una serie di istruzioni nop , quindi il salto non viene mai preso e il risultato è sempre vero. In questo modo, qualsiasi chiave di licenza è accettata. Ancora meglio, potrei semplicemente modificare l'inizio del metodo per impostare immediatamente eax su 1 e restituire, quindi non è nemmeno più fastidioso chiedere al server la convalida della licenza.

Quindi, come risolviamo questo problema? Sfortunatamente per te, non possiamo. Ti stai imbattendo nel problema del DRM, che in sostanza afferma che se si consegnano a qualcuno dei dati, possono sempre modificarli. Indipendentemente da quanto offuscate il vostro codice, è possibile che l'utente lo decodifichi e che elabori le modalità per apportare modifiche o estrarre i dati. Se decidi di crittografare il contenuto, alla fine devi avere la chiave sul sistema per decodificarlo, quindi c'è sempre un modo per l'utente di estrarre quella chiave e decodificare il contenuto in modo permanente.

Il meglio che puoi fare è renderlo difficile, il che richiede molto tempo e impegno. Alla fine il tuo software sarà rotto e finirà su un sito torrent da qualche parte. Fa schifo agli sviluppatori che usano questo tipo di modello di business, ma è il mondo in cui viviamo. Il mio suggerimento è che tu scenda su una delle due rotte:

  1. Crea un sistema di licenze di base che funzioni e accetta il fatto che alcune persone lo pirocheranno. Servi i tuoi clienti reali spendendo i tuoi tempi di sviluppo effettivamente apportando miglioramenti al software, piuttosto che implementando e mantenendo sistemi DRM draconiani.

  2. Cambia il tuo intero paradigma di sviluppo e di business, in modo che il tuo prodotto sia un servizio piuttosto che un'applicazione software. SaaS ha avuto molto successo, dato che è (praticamente) impossibile da piratare i servizi, e il modello ti permette di fare in tempo reale modifiche alla base di codice ed eseguire analisi sull'utilizzo.

Se vai per l'opzione 1, non coinvolgere un server per la convalida. Aggiunge complessità, non offre alcuna sicurezza aggiuntiva, comporta alcuni problemi di privacy e impedisce agli utenti di utilizzare il software se il server delle licenze non funziona. Basta attaccare con qualcosa di semplice, ad es. un hash del nome utente e un valore segreto sul lato client. È banale da rompere, ma offre una barriera minima alla pirateria.

    
risposta data 24.10.2012 - 11:25
fonte
1

Se tutto ciò che si sta tentando di fare è generare una chiave di licenza che è difficile da replicare, utilizzando il nome utente come parte dell'input dell'hash in realtà si renderà la chiave di licenza più debole e quindi più facile da indovinare. Il nome utente non è casuale e quindi diminuisce l'entropia della chiave di licenza risultante, e il nome utente può essere indovinato dall'attaccante che potrebbe quindi, facendo alcune ipotesi sul metodo, forzare la chiave in modo più semplice.

Se stai aggiungendo una stringa casuale al nome utente, non ci sono buoni motivi per usare il nome utente, basta usare tutti i dati casuali. L'unica ragione per cui useresti il nome utente per generare la chiave di licenza sarebbe renderla reversibile.

    
risposta data 24.10.2012 - 11:07
fonte
-1

Oppure potresti inviare all'utente un'email con un link di verifica. una volta che fanno clic sul collegamento, il server sa che il software è legittimo. l'app periodicamente "telefona a casa" per verificare se è stata verificata e diventa a funzionalità limitata se riceve una risposta negativa.

Questo potrebbe anche proteggere da attivazioni multiple eccessive, in quanto il server saprebbe quante licenze ha un utente e quante ne sono state utilizzate. Ovviamente tutte le comunicazioni tra l'app e il server sono tramite ssl.

    
risposta data 24.10.2012 - 12:27
fonte

Leggi altre domande sui tag