* * * *

Privacy Policy

Forum ufficiale

Se non siete riusciti a reperire l'informazione che cercavate nei nostri articoli o sul nostro forum vi consiglio di visitare il
Forum ufficiale di Lazarus in lingua inglese.

Lazarus 1.0

Trascinare un file nel programma
DB concetti fondamentali e ZeosLib
Recuperare codice HTML da pagina web
Mandare mail con Lazarus
Stabilire il sistema operativo
Esempio lista in pascal
File INI
Codice di attivazione
Realizzare programmi multilingua
Lavorare con le directory
Utilizzare Unità esterne
TTreeView
TTreeview e Menu
Generare controlli RUN-TIME
LazReport, PDF ed immagini
Intercettare tasti premuti
Ampliare Lazarus
Lazarus e la crittografia
System Tray con Lazarus
UIB: Unified Interbase
Il file: questo sconosciuto
Conferma di chiusura di un applicazione
Liste e puntatori
Overload di funzioni
Funzioni a parametri variabili
Proprietà
Conversione numerica
TImage su Form e Panel
Indy gestiore server FTP lato Client
PopUpMenu sotto Pulsante (TSpeedButton)
Direttiva $macro
Toolbar
Evidenziare voci TreeView
Visualizzare un file Html esterno
StatusBar - aggirare l'errore variabile duplicata
Da DataSource a Excel
Le permutazioni
Brute force
Indy 10 - Invio email con allegati
La gestione degli errori in Lazarus
Pascal Script
Linux + Zeos + Firebird
Dataset virtuale
Overload di operatori
Lavorare con file in formato JSON con Lazarus
Zeos ... dietro le quinte (prima parte)
Disporre le finestre in un blocco unico (come Delphi)
Aspetto retrò (Cmd Line)
Lazarus 1.0
Come interfacciare periferica twain
Ubuntu - aggiornare free pascal e lazarus
fpcup: installazioni parallele di lazarus e fpc
Free Pascal e Lazarus sul Raspberry Pi
Cifratura: breve guida all'uso dell'algoritmo BlowFish con lazarus e free pascal.
Creare un server multithread
guida all'installazione di fpc trunk da subversion in linux gentoo
Indice
DB concetti fondamentali e connessioni standard
Advanced Record Syntax
DB concetti fondamentali e DBGrid
DB concetti fondamentali e TDBEdit, TDBMemo e TDBText
Advanced Record Syntax: un esempio pratico
Superclasse form base per programmi gestionali (e non)
Superclasse form base per programmi gestionali (e non) #2 - log, exception call stack, application toolbox
Superclasse form base per programmi gestionali (e non) #3 - traduzione delle form
Superclasse form base per programmi gestionali (e non) #4 - wait animation
Un dialog per la connessione al database:TfmSimpleDbConnectionDialog
Installare lazarus su mac osx sierra
immagine docker per lavorare con lazarus e free pascal
TDD o Test-Driven Development
Benvenuto! Effettua l'accesso oppure registrati.
Settembre 26, 2020, 10:57:58 pm

Inserisci il nome utente, la password e la durata della sessione.

17 Visitatori, 0 Utenti

21 Ott 2011 - Codice di attivazione

Cosa succede quando avete finito un software e volete distribuirlo, previa vostra autorizzazione? Questo How To vi viene incontro e vi spiega come io ho affrontato il problema.

La soluzione a tale problema è composta di due parti, un codice php posizionato nel sito dal quale distribuisco il software e dal quale faccio fare l'attivazione del prodotto.


Quella che segue è la classe PHP che mi genera il mio codice di attivazione nel formato: XXXX-XXXX-XXXX-XXXX


[code]

/*

    Classe realizzata da Sammarco Francesco
    Es:

    $OggettoSN = new Serial_Number;
    $CodSer = $OggettoSN->PKV_MakeKey($IdCod);
*/

class Serial_Number
{

    // Costruttore
    function __construct()
    {
    }

    // Distruttore
      public function __destruct()
    {
            //non faccio niente
    }
    private function Shr($a, $b)
    {
        return ($a/(2^$b));
    }


    private function PKV_GetKeyByte($Seed,$a,$b,$c)
    {
        $a = $a % 25;
        $b = $b % 3;
        if( $a % 2 == 0 )
        {
          $result = ( $Seed >> $a ) ^ ( ( $Seed >> $b ) | $c );
        } else
        {
          $result = ( $Seed >> $a ) ^ ( ( $Seed >> $b ) & $c );
        }
        return $result & 0x000000FF;
       }

       private function IntToHex($Variabile,$Num)
       {
           $result=dechex($Variabile);
           $k=$Num-strlen($result);
           for($i=0;$i<$k;$i++)
           {
               $result="0" . $result;
           }
           return strtoupper($result);
       }

    public function PKV_MakeKey($Seed)
    {
          $KeyBytes[0]=$this->PKV_GetKeyByte($Seed, 24, 3, 200);
          $KeyBytes[1]=$this->PKV_GetKeyByte($Seed, 10, 0, 56);
          $KeyBytes[2]=$this->PKV_GetKeyByte($Seed, 1, 2, 91);
          $KeyBytes[3]=$this->PKV_GetKeyByte($Seed, 7, 1, 100);

          $result=$this->IntToHex($Seed,8);
          for ($i=0;$i<=3;$i++)
          {
              $result=$result . $this->IntToHex($KeyBytes[$i],2);
          }
          $valorecs=$this->PKV_GetChecksum($result);
          $result=$result . $valorecs;
          $app="";
          $j=1;
          for ($i=0;$i<strlen($result);$i++)

          {
              if (($j == 4)&&($i<(strlen($result)-1)))
              {
                  $app=$app . $result[$i] . "-";
                  $j=1;
              }else
              {
                  $app=$app . $result[$i];
                  $j++;
              }
          }
          return $app;
    }

    private function PKV_GetChecksum($s)
    {
          $left = 0x0056;
          $right = 0x00AF;
        if(strlen($s) > 0 )
        {
            for( $i = 0 ; $i < strlen( $s ) ; $i++ )
            {
                  $right = $right + Ord($s[$i]);
                  if($right > 0x00FF )
                  {
                    $right=$right-0x00FF;
                }
                  $left=$left+$right;
                  if($left > 0x00FF )
                  {
                    $left=$left-0x00FF;
                }
            }
        }
          $sum = ( $left << 8 ) + $right;
          $result = $this->IntToHex($sum, 4 );
        return $result;
    }

}

?>

[/code]




Usare tale classe è molto molto semplice basta usare il codice (sempre in php):

    $OggettoSN = new Serial_Number;
    $CodSer = $OggettoSN->PKV_MakeKey($IdCod);   

Dove $IdCod equivale all'inizializzatore da cui mi ricavo il mio codice di attivazione e $CodSer è il nostro tanto agognato codice di serie.

Per rendere la nostra classe unica e diversa da questo codice di esempio basta cambiare i parametri numerici nella funzione PKV_GetKeyByte

         $KeyBytes[0]=$this->PKV_GetKeyByte($Seed, 24, 3, 200);
         $KeyBytes[1]=$this->PKV_GetKeyByte($Seed, 10, 0, 56);
         $KeyBytes[2]=$this->PKV_GetKeyByte($Seed, 1, 2, 91);
         $KeyBytes[3]=$this->PKV_GetKeyByte($Seed, 7, 1, 100);

Ora questa parte scritta in PHP crea un codice che comunico (tramite mail automatica) all'interessato.

Ora toccherà al programma (scritto in Lazarus) elaborare questa informazione, e io ho scritto una libreria per fare questo:

[code]

unit MySerialNumber;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils;

  const
  KEY_GOOD = 0;
  KEY_INVALID = 1;
  KEY_BLACKLISTED = 2;
  KEY_PHONY = 3;

  type
      SerialNumber=object
      private
      public
            function PKV_GetKeyByte(const Seed : Int64; a, b, c : Byte) : Byte;
            function PKV_CheckKey(const S : String) : Integer;
            function PKV_CheckKeyChecksum(const Key : String) : Boolean;
            function PKV_MakeKey(const Seed : Int64) : String;
            function PKV_GetChecksum(const s : String) : String;
      end;
var
                BL : array[0..0] of String = ('11111111');
implementation

{ serial number }
function StartsStr(str: string; inizio: string): boolean;
var
    Esci: boolean;
    ret: boolean;
    i: integer;
    len1: integer;
    len2: integer;
begin
    len1:=length(str);
    len2:=length(inizio);
    ret:=false;
    if len1>=len2 then
    begin
        i:=0;
        ret:=TRUE;
        if len1=0 then
            Esci:=TRUE
        else
            Esci:=FALSE;
        while (Esci=False) do
        begin
            if str[i]<>inizio[i] then
            begin
                Esci:=TRUE;
                ret:=FALSE;
            end;
            Inc(i);
            if i>len1 then
                Esci:=TRUE;
        end;
    end;
    StartsStr:=ret;
end;

function SerialNumber.PKV_GetKeyByte(const Seed : Int64; a, b, c : Byte) : Byte;
var
   risultato: byte;
begin
  a := a mod 25;
  b := b mod 3;
 if a mod 2 = 0 then
    risultato := ((Seed shr a) and $000000FF) xor ((Seed shr b) or c)
  else
    risultato := ((Seed shr a) and $000000FF) xor ((Seed shr b) and c);
    PKV_GetKeyByte:=risultato;
end;

function SerialNumber.PKV_GetChecksum(const s : String) : String;
var
  left, right, sum : Word;
  i : Integer;
  app: string;
begin
  left := $0056;
  right := $00AF;
if Length(s) > 0 then
    for i := 1 to Length(s) do
    begin
      right := right + Byte(s[i]);
      //app:= app + 'r: ' + s[i] + '(' + IntToStr(Byte(s[i])) + ')';
      //right := right + Byte(s[i]);
      if right > $00FF then
        Dec(right, $00FF);
      Inc(left, right);
      if left > $00FF then
        Dec(left, $00FF);
    end;
  sum := (left shl 8) + right;
  result := IntToHex(sum, 4);
end;

function SerialNumber.PKV_MakeKey(const Seed : Int64) : String;
var
  KeyBytes : array[0..3] of Byte;
  i : Integer;
  app: string;
begin
  // Fill KeyBytes with values derived from Seed.
  // The parameters used here must be extactly the same
  // as the ones used in the PKV_CheckKey function.
  // A real key system should use more than four bytes.
  KeyBytes[0] := PKV_GetKeyByte(Seed, 24, 3, 200);
  KeyBytes[1] := PKV_GetKeyByte(Seed, 10, 0, 56);
  KeyBytes[2] := PKV_GetKeyByte(Seed, 1, 2, 91);
  KeyBytes[3] := PKV_GetKeyByte(Seed, 7, 1, 100);
   // the key string begins with a hexidecimal string of the seed
  result := IntToHex(Seed, 8);
// then is followed by hexidecimal strings of each byte in the key
  for i := 0 to 3 do
  begin
    result := result + IntToHex(KeyBytes[i], 2);
  end;
// add checksum to key string
  result := result + PKV_GetChecksum(result);
// Add some hyphens to make it easier to type
  i := Length(result) - 3;
  while (i > 1) do
  begin
    Insert('-', result, i);
    Dec(i, 4);
  end;
end;

function SerialNumber.PKV_CheckKeyChecksum(const Key : String) : Boolean;
var
  s, c : String;
begin
  result := False;
 // remove cosmetic hypens and normalize case
  s := UpperCase(StringReplace(Key, '-', '', [rfReplaceAll]));
  if Length(s) <> 20 then
    exit; // Our keys are always 20 characters long
  // last four characters are the checksum
  c := Copy(s, 17, 4);
  SetLength(s, 16);
// compare the supplied checksum against the real checksum for
  // the key string.
  result := c = PKV_GetChecksum(s);
end;


function SerialNumber.PKV_CheckKey(const S : String) : Integer;
var
  Key, kb : String;
  Seed : Int64;
  i : Integer;
  b : Byte;
begin
  result := KEY_INVALID;
  if not PKV_CheckKeyChecksum(S) then
    exit; // bad checksum or wrong number of characters
 // remove cosmetic hypens and normalize case
  Key := UpperCase(StringReplace(S, '-', '', [rfReplaceAll]));
 // test against blacklist
  if Length(BL) > 0 then
    for i := Low(BL) to High(BL) do
      if StartsStr(BL[i], Key) then
      begin
        result := KEY_BLACKLISTED;
        exit;
      end;
// At this point, the key is either valid or forged,
  // because a forged key can have a valid checksum.
  // We now test the "bytes" of the key to determine if it is
  // actually valid.
// When building your release application, use conditional defines
  // or comment out most of the byte checks!  This is the heart
  // of the partial key verification system. By not compiling in
  // each check, there is no way for someone to build a keygen that
  // will produce valid keys.  If an invalid keygen is released, you
  // simply change which byte checks are compiled in, and any serial
  // number built with the fake keygen no longer works.
// Note that the parameters used for PKV_GetKeyByte calls MUST
  // MATCH the values that PKV_MakeKey uses to make the key in the
  // first place!
result := KEY_PHONY;
 // extract the Seed from the supplied key string
  if not TryStrToInt64('$' + Copy(Key, 1, 8), Seed) then
    exit;
{$IFDEF KEY00}
  kb := Copy(Key, 9, 2);
  b := PKV_GetKeyByte(Seed, 24, 3, 200);
  if kb <> IntToHex(b, 2) then
    exit;
  {$ENDIF}
{$IFDEF KEY01}
  kb := Copy(Key, 11, 2);
  b := PKV_GetKeyByte(Seed, 10, 0, 56);
  if kb <> IntToHex(b, 2) then
    exit;
  {$ENDIF}
  {$IFDEF KEY02}
  kb := Copy(Key, 13, 2);
  b := PKV_GetKeyByte(Seed, 1, 2, 91);
  if kb <> IntToHex(b, 2) then
    exit;
  {$ENDIF}
  {$IFDEF KEY03}
  kb := Copy(Key, 15, 2);
  b := PKV_GetKeyByte(Seed, 7, 1, 100);
  if kb <> IntToHex(b, 2) then
    exit;
  {$ENDIF}
 // If we get this far, then it means the key is either good, or was made
  // with a keygen derived from "this" release.
result := KEY_GOOD;
end;

end.


[/code]

Quello che è importante è che i valori numerici della funzione PKV_GetKeyByte siano valorizzati in maniera identica con quelli del codice PHP

  KeyBytes[0] := PKV_GetKeyByte(Seed, 24, 3, 200);
  KeyBytes[1] := PKV_GetKeyByte(Seed, 10, 0, 56);
  KeyBytes[2] := PKV_GetKeyByte(Seed, 1, 2, 91);
  KeyBytes[3] := PKV_GetKeyByte(Seed, 7, 1, 100);


Per poter sfruttare questa libreria bastano poche linee di codice in free pascal

     if length(Codice)=24 then
     begin
          Valore:=MioOggetto.PKV_CheckKey(Codice);
          if Valore=0 then
          begin

                 {CODICE DI ATTIVAZIONE VALIDO}
          end;
     end;

Dove la variabile Codice è valorizzata con il codice che precedentemente avevamo comunicato al nostro cliente.

Bene questa è la soluzione che avevo usato io in uno dei miei progetti. Se avete altre soluzioni non esitate a comunicarmele e vedrò di pubblicarle. Avverto che pubblicherò solo soluzioni che possono essere multipiattaforma.


Share on Twitter! Digg this story! Del.icio.us Share on Facebook! Technorati Reddit StumbleUpon

Articles in « Lazarus 1.0 »

Comments *

1) Re: Codice di attivazione
Written by antoniog il Ottobre 11, 2013, 02:45:43 am
Molto interessante! mi piacerebbe svilupparlo ed usarlo, è possibile avere un esempio funzionante da scaricare. grazie
Commenting option has been turned off for this article.

Recenti

How To

Utenti
Stats
  • Post in totale: 13879
  • Topic in totale: 1742
  • Online Today: 31
  • Online Ever: 900
  • (Gennaio 21, 2020, 08:17:49 pm)
Utenti Online
Users: 0
Guests: 17
Total: 17

Disclaimer:

Questo blog non rappresenta una testata giornalistica poiché viene aggiornato senza alcuna periodicità. Non può pertanto considerarsi un prodotto editoriale ai sensi della legge n. 62/2001.