Written by xinyiman Ottobre 21, 2011, 11:09:00 am22150 ViewsRating: 0 (0 Rates)Print
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));
}
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
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.
About the author
xinyiman registered at Italian community of Lazarus and Free Pascal on Ottobre 14, 2011, 10:56:28 pm and has posted 3269 posts in the boards since then. Last visit was Oggi alle 08:25:57 am.
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.
Questo sito utilizza cookie, anche di terze parti, per offriti servizi in linea con le tue preferenze. Chiudendo questo banner, scorrendo questa pagina, cliccando su un link o proseguendo la navigazione in altra maniera, acconsenti all’uso dei cookie.