Privacy Policy

Blog italiano

Clicca qui se vuoi andare al blog italiano su Lazarus e il pascal.

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

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

Recenti

How To

Utenti
Stats
  • Messaggi totali: 20.582
  • Totale discussioni: 2.471
  • Online today: 310
  • Online ever: 5.949 (Luglio 30, 2026, 09:49:59 PM)
Utenti online
  • Users: 0
  • Guests: 15
  • Total: 15
15 Visitatori, 0 Utenti

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 Facebook!Share on Twitter!RedditDigg this story!Del.icio.usStumbleUpon

Comments: 1 *

1) Re: Codice di attivazione
Comment 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
You don't have permission to comment, or comments have been turned off for this article.

Articles in « Lazarus 1.0 »

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.