2010-09-10 12 views
5

Durante i miei giorni come programmatore PHP e principiante alla programmazione C# mi sono sempre chiesto quale sia il modo migliore per generare serie uniche come il modo in cui operano Microsoft Office e Microsoft.Generazione seriale con PHP

Qualcuno ha una buona guida su come gestirlo, come quali sono i fattori importanti nella generazione della seriale univoca, evitare duplicati ecc. Piccolo esempio su come crearli/verificarli.

Ecco la RFC di cui sto parlando: http://tools.ietf.org/html/rfc1982.

risposta

12

Se l'applicazione ha una connessione al server è banale, è sufficiente generare token casuali, archiviarli in un database e richiedere all'applicazione di ricontrollare il server prima dell'esecuzione. Tuttavia, alcuni clienti potrebbero ritenere questo requisito inaccettabile. (Io personalmente potrò mai comprare qualsiasi software con un fabbisogno di attivazione internet voglio comprare software, non affittarlo..)

Per i tasti con checkability genuinità, senza dover disporre di una connessione al server:

  1. Sul server, genera un token univoco casuale.

  2. Utilizzare uno schema di crittografia a chiave pubblica (ad esempio RSA) per firmare il token con una chiave privata che viene tenuta segreta al server.

  3. Codifica il token univoco e la firma insieme utilizzando uno schema da binario a testo (ad esempio base64, o semplicemente utilizzando i simboli 2-9A-KMNP-Z per una maggiore praticabilità). La combinazione codificata è la tua chiave o seriale.

  4. Incorporare la chiave pubblica corrispondente alla chiave privata del server in ogni copia dell'applicazione e richiedere l'immissione di una chiave al momento dell'installazione. Può dividere il token univoco e la firma e utilizzare la chiave pubblica per verificare che la firma sia valida per quel token.

Questo approccio richiede si bundle alcune librerie crittografiche con il software, e la maggior parte degli algoritmi usano abbastanza lunghe firme, per la sicurezza, che renderà i numeri di serie abbastanza noioso da digitare. Va bene se si prevede che agli utenti di copiare -e incolla i numeri.

Per questi motivi molti pacchetti software utilizzano uno schema di convalida della chiave meno sicuro in cui l'algoritmo di controllo è interamente integrato nel client. Questo potrebbe essere un hash, ad es. le ultime quattro cifre esadecimali del serial devono corrispondere ai due byte più bassi dell'hash SHA1 del resto del serial combinato con una chiave 'secret'. Tuttavia, poiché la chiave deve essere raggruppata nell'applicazione, è possibile che un hacker guardi il codice dell'app ed estragga la chiave "segreta", consentendo loro di scrivere i propri generatori di chiavi.

Ecco perché per alcuni programmi sono disponibili "keygen" disponibili: l'app utilizza un controllo di sicurezza meno sicuro che ha lasciato abbastanza informazioni nell'applicazione per consentire al cracker di riprodurre il processo decisionale. Per i programmi con un'impostazione più sicura basata su crittografia a chiave pubblica o sull'attivazione di Internet, in genere viene visualizzata una versione "crackata" dell'applicazione, in cui il codice di controllo è stato modificato/rimosso.

... che tipo di dimostrazione che qualunque cosa tu faccia, non sarai ancora in grado di far rispettare l'onestà. Quindi non preoccuparti troppo di questo.

+0

Buono tutto informazioni – Fanis

+0

Perfetto, solo il tipo di informazioni che stavo cercando :), Ottima lettura. +1 – RobertPitt

+1

: -/questo è esattamente quello che ho detto. – Bot

1

Non sono assolutamente sicuro di ciò che si desidera, ma c'è http://www.php.net/manual/en/function.uniqid.php che crea identificatori univoci.

Se sei più interessato a come vengono creati, ti consiglio di dare un'occhiata al sorgente PHP per vedere come viene implementato uniqid.

+0

Im parlando per quanto riguarda http://tools.ietf.org/html/rfc1982 – RobertPitt

+0

uniqid è perfettamente prevedibile. In realtà è solo una rappresentazione della microtime in cui è stato generato. Non è in alcun modo casuale. – NikiC

1

Sono necessarie ulteriori informazioni. Stai cercando di creare un codice seriale come quando acquisti un gioco o desideri un serial per un ID utente univoco.

I numeri seriali devono memorizzare informazioni quali una data/ora di scadenza?

@nikic - il tempo di utilizzo di tutti i rand come base per l'avvio del generatore casuale. Questo è il motivo per cui il Dipartimento della Difesa usa lampade laviche. Hanno un'intera stanza dedicata a lampade laviche e lucidi laser su di essi per creare casualmente una chiave unica.

Modificato:

Bene ciò che è necessario prendere in effetto è quale metodo il vostro # applicazione C utilizzerà per comunicare con il tuo sito.

Sarà necessario creare una chiave con php e memorizzarla nel database in modo che il C# possa confermare che la serie è corretta.

Quindi è necessario capire se il PHP restituirà un altro valore in modo che l'applicazione C# sia a conoscenza che la chiave è stata autenticata o meno.

Quello che ho fatto in passato è stato creare una chiave pubblica e una chiave privata. La chiave pubblica verrà data all'utente per convalidare il prodotto. Quando convalidano il prodotto o effettuano l'accesso al sistema, la chiave pubblica verrebbe controllata rispetto al database e il valore restituito sarebbe la chiave privata. Durante tutte le interazioni con il mio programma C#, se l'utente ha bisogno di controllare gli aggiornamenti o di estrarre informazioni dal mio server, la chiave privata verrà aggiunta alla query sul server per confermare che l'utente finale è legittimo.

Un altro metodo che ho utilizzato è il precedente ma ha aggiunto un controllo aggiuntivo per confermare che l'utente non stava condividendo la chiave. L'applicazione C# otterrebbe il numero seriale del processore nel computer e al momento della registrazione dell'applicazione lo salverebbe nel mio database. Quindi, se qualcun altro ha tentato di registrare il prodotto con la stessa chiave pubblica ma un diverso numero di serie del processore genererebbe un errore e sarebbe stato necessario contattare l'assistenza. Puoi farlo per consentire 5 diversi ID macchina o quanti ne vuoi.

La creazione del codice di registrazione è molto semplice in quanto è sufficiente creare una stringa casuale con un offset (ad esempio il nome dell'utente).

È inoltre possibile creare un codice di registrazione basato su un nome o nome di società fornito da qualcuno e aggiungere tale algoritmo al programma C#. Il lato negativo di questo è il codice sorgente C# può essere decompilato facilmente l'algoritmo può essere trovato per creare facilmente un codice di registrazione senza che qualcuno paghi effettivamente il prodotto.Aggiungendo un server che esegue l'autenticazione è molto più difficile per qualcuno generare la propria chiave seriale.

+0

diciamo che ho un prodotto, come un'applicazione, questa applicazione richiede un sistema seriale, voglio generare un seriale in PHP che può essere controllato e convalidato in C#, quali fattori devo impiegare in uno script per essere in grado per generare e verificare una chiave A indipendentemente da quale interprete. – RobertPitt

+0

Ho modificato la mia risposta per mostrare alcuni esempi di ciò che ho fatto nell'incollato. – Bot

1

Se si desidera creare centralmente numeri seriali casuali, è sufficiente prelevare casualmente da una matrice di numeri e lettere. Usa mt_rand(0, count($poolArray)) per ottenere ogni volta un nuovo indice e aggiungi quel carattere al tuo numero di serie fino a quando ne hai 12.

Generandoli in modo casuale da una piscina di grandi dimensioni (26 lettere + 10 cifre) sarà quasi certo di non avere duplicati, ma è sempre possibile controllare quelli esistenti prima di memorizzare quello nuovo.

Se si dispone di 36 caratteri possibili e si selezionano 12 a caso da essi per creare i numeri di serie, ciò è 36 * 36 * 36 * ... * 36 = 36^12 = 4738381338321616896 stringhe possibili.

$pool = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 
$countPool = count($pool) ; 
$totalChars = 12 ; 

$serial = '' ; 
for ($i = 0 ; $i < $totalChars ; $i++) { 
    $currIndex = mt_rand(0, $countPool) ; 
    $currChar = $pool[$currIndex] ; 
    $serial .= $currChar ; 
} 

Distribuirli con il codice o fare in modo che il programma verifichi la presenza di un numero seriale valido è un altro problema.

+0

Mi dispiace, perché con 'count ($ pool)' dammi risultato 101000100100 mentre se assegno esplicitamente 35, funziona 3UNPWR3GWHQP, e se assegno 36, va con offset unitializzato – Zyoo

+0

@ yolapop sei assolutamente corretto. Volevo scrivere $ pool come array ma in qualche modo ho finito per scriverlo come una stringa. Consideralo un array e la metodologia funziona. – Fanis

11

Risposta molto tardiva a una domanda già ben fatta, ma ecco la nostra soluzione. Genera una chiave con dimensione/lunghezza configurabile e suffisso opzionale basato su IPv4 valido, Userid (o qualsiasi intero significativo) o stringa di testo. Evita anche caratteri ambigui (i, 1, l, 0, o, O) nel risultato standard.

Aggiungiamo l'ID utente nella licenza e possiamo successivamente riconvertire quella parte in un numero intero di base10 e verificare se è valida contro l'account utente che sta utilizzando la licenza.

$license = generate_license(); 
// YF6G2-HJQEZ-8JZKY-8C8ZN 

$license = generate_license(123456); 
// ZJK82N-8GA5AR-ZSPQVX-2N9C 

$license = generate_license($_SERVER['REMOTE_ADDR']); 
// M9H7FP-996BNB-77Y9KW-ARUP4 

$license = generate_license('my text suffix'); 
// Q98K2F-THAZWG-HJ8R56-MY-TEXT-SUFFIX 

Facciamo il check unicità nel database al momento della creazione, ma utilizzando l'IP/Userid in concomitanza con la casualità, la probabilità di duplicati è praticamente pari a zero.

/** 
* Generate a License Key. 
* Optional Suffix can be an integer or valid IPv4, either of which is converted to Base36 equivalent 
* If Suffix is neither Numeric or IPv4, the string itself is appended 
* 
* @param string $suffix Append this to generated Key. 
* @return string 
*/ 
function generate_license($suffix = null) { 
    // Default tokens contain no "ambiguous" characters: 1,i,0,o 
    if(isset($suffix)){ 
     // Fewer segments if appending suffix 
     $num_segments = 3; 
     $segment_chars = 6; 
    }else{ 
     $num_segments = 4; 
     $segment_chars = 5; 
    } 
    $tokens = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789'; 
    $license_string = ''; 
    // Build Default License String 
    for ($i = 0; $i < $num_segments; $i++) { 
     $segment = ''; 
     for ($j = 0; $j < $segment_chars; $j++) { 
      $segment .= $tokens[rand(0, strlen($tokens)-1)]; 
     } 
     $license_string .= $segment; 
     if ($i < ($num_segments - 1)) { 
      $license_string .= '-'; 
     } 
    } 
    // If provided, convert Suffix 
    if(isset($suffix)){ 
     if(is_numeric($suffix)) { // Userid provided 
      $license_string .= '-'.strtoupper(base_convert($suffix,10,36)); 
     }else{ 
      $long = sprintf("%u\n", ip2long($suffix),true); 
      if($suffix === long2ip($long)) { 
       $license_string .= '-'.strtoupper(base_convert($long,10,36)); 
      }else{ 
       $license_string .= '-'.strtoupper(str_ireplace(' ','-',$suffix)); 
      } 
     } 
    } 
    return $license_string; 
} 
2

La mia soluzione

implode('-', str_split(substr(strtoupper(md5(time() . rand(1000, 9999))), 0, 20), 4)); 
+0

Questo è molto elegante! –

+0

Buono! dato il numero di serie puoi decodificare fino alla data? –