PDA

Visualizza versione completa : Identificare una macchina univocamente...???


stzlu
14-07-2012, 15.58.43
salve a tutti,
e da tempo che leggo questo forum, e oggi ho deciso di chiedervi un aiuto...

Dovendo realizzare un'applicazione desktop in java che deve avere come funzione primaria il fatto che l'applicazione devi girare una sola volta su ogni computer, nel senso che l'applicazione non potrà essere eseguita più di una volta su ogni singola macchina, questo per evitare attività fraudolente.

Quindi avrei bisigno di un id che identifichi univocamente ogni singolo pc.

Nel forum ho trovato discussioni simili, che risolvono tale problema identificando il pc con il mac address, ma tale soluzione non è adatta per la mia applicazione, poichè essendo un'applicazione descktop che può girare anche senza connessione internet, quando il pc non è connesso il mac address mi tornerà null, impedendo di identificare la macchina.

Perciò dovrei identificare il pc mediante qualche altre id, non so se si può leggere quello della scheda madre o di qualche altre componente, che sia però un id identificativo UNIVOCO, per ogni singola macchina, in modo che un pc non venga scambiato per un altro pc che ha già utilizzato l'applicazione.

Spero in un vostro aiuto, perchè al momento sono ad un punto morto e non so proprio come andare avanti.

Un ringraziamento anticipato a tutti! :)

borgata
14-07-2012, 16.54.08
Il MAC address è in ogni caso modificabile, quindi non è granchè come soluzione.
Inoltre è legata ad un singolo componente della macchina, la scheda di rete, che può essere facilmente sostituita.

Direi che una buona soluzione potrebbe essere quella di raccogliere dati dal pc, per esempio gli id dell'hardware e magari la key del sistema operativo, e creare una hash in base a questi.

Ovviamente ci sono delle problematiche, come per esempio il fatto che questo non garantisce l'univocità, oppure il fatto che il cambio di un componente hardware potrebbe impedire al programma di funzionare.

In alternativa, su sistemi windows, potresti inserire qualche chiave nascosta nel registro (operazione io odio perchè questi programmi sporcano terribilmente il registro, e ovviamente è anche facilmente aggirabile... anche qui dipende dal livello di sicurezza che vuoi raggiungere).

poi dipende anche da come concedi questa "licenza".
Puoi lavorare in automatico con tua applicazione che fa la verifica su un database online, oppure raccogliere i dati e attivare una license key ad hoc per la macchina.

Altrimenti potresti attivare delle key personali basate per esempio su piva o codice fiscale, ma ovviamente questo non lega il software ad una specifica macchina.

Insomma, soluzioni ce ne sono tante, ma nessuna è del tutto sicura, devi solo vedere quale è la più adeguata alle tue esigenze.

stzlu
14-07-2012, 17.24.56
Direi che una buona soluzione potrebbe essere quella di raccogliere dati dal pc, per esempio gli id dell'hardware e magari la key del sistema operativo, e creare una hash in base a questi.

Ovviamente ci sono delle problematiche, come per esempio il fatto che questo non garantisce l'univocità, oppure il fatto che il cambio di un componente hardware potrebbe impedire al programma di funzionare.

ti ringrazio per il tuo riassuntivo ed esauriente elenco di soluzioni. quello degli id dell'hardware è a mio avviso uno dei migliori.
Visto che l'applicazione in questione fa riferimento ad una sorta di registrazione del programma (anche se non è proprio così ma non entro nel dettaglio per non complicare), che deve essere eseguita una sola volta per ogni pc, per cui l'elenco degli id dell'hardware al momento della registrazione mi potrebbe bastare, se poi per aggirare il blocco si è disposti a sostituire i componenti del pc... sarebbero casi non troppo diffusi che sono disposto a tollerare!

Ora mi chiedo quali siano gli id dell'hardware migliori da prendere in considerazione e come reperirli... cosa mi consigli?

Grazie ancora.

roberto45
14-07-2012, 17.28.20
Una soluzione potrebbe essere un algoritmo che crei un codice legato ad un checksum del firmware e/o al nome del disco rigido e conservarlo sul 1° settore non usato del disco rigido, un tempo con la FAT era semplice metterlo sul cilindro 0 ; anche in questo caso però cambiando la scheda madre e/o il disco rigido il problema si ripropone.

retalv
14-07-2012, 17.51.40
Quindi avrei bisigno di un id che identifichi univocamente ogni singolo pc.

Provo a dire la mia...

Premesso che di Java non ne so mezza, avrei trovato questo link (http://www.rgagnon.com/javadetails/java-0580.html) con le routine per leggere il numero di serie di matherboard e HDs.

Il problema però non è cosa andare a leggere e come, ma come memorizzare queste letture: parli di registrazione, in linea, locale..?

Se distribuisci su supporto a sola lettura sei costretto a scriverle da qualche parte sulla macchina, mentre se le distribuisci su supporto scrivibile sei costretto a identificare il supporto che distribuisci e a inserire l'identificazione dentro l'applicativo.

Se il tuo applicativo è multipiattaforma le cose si complicano ulteriormente.

A questo punto la cosa più semplice (se distribuisci solo per Windows) è usare i registry su chiave nascosta in HKEY_CLASSES_ROOT salvando l'identificativo utente e qualche altro parametro relativo all'hardware, ma rimane il fatto che con un semplice salvataggio e comparazione dello stato dei registri può essere facilmente individuato.

Per tagliare la testa al toro, dovresti forzatamente distribuire l'applicativo con un supporto scrivibile e identificabile e creare su questo il database dei parametri macchina, in altre parole una chiavetta in cui riesci a leggere produttore e seriale della stessa, ma anche tener conto di identificare il dbase dei parametri sempre in relazione a seriale e produttore: in altre parole il dbase deve contenere i riferimenti alla chiavetta e alla data di creazione/modifica del dbase legandolo ad una posizione ben definita del supporto, in modo che se viene cancellato o modificato per fare la "furbata" non possa essere ricreato-usato dall'applicativo che distribuisci.

Ma anche qui con un bel programma di copia settore per settore... ;)

E' un discorso contorto, ma spero di aver dato un senso al ragionamento. ;)

stzlu
14-07-2012, 20.48.45
Premesso che di Java non ne so mezza, avrei trovato questo link (http://www.rgagnon.com/javadetails/java-0580.html) con le routine per leggere il numero di serie di matherboard e HDs.


Grazie per il link che mi sembra molto interessante... ora provo ad implemetare le mie classi java!

Comunque, per tener traccia dei dati della macchina avevo pensato di affiancare all'applicativo in file dat criptato con i dati e offuscare il codice dell'applicazione che effettuerà le opportune verifiche circa la possibile o meno registrazione.

per gli id pensavo a questo punto di usare quelli della Motherboard e dell' hd, ma poichè nella materia di componentistica non sono proprio ferrato, mi chiedevo se gli id della Motherboard e del hd sono assoulutamente univoci, nel senso che non possono esistere due Motherboards o hd con lo stesso ID?!?

retalv
15-07-2012, 20.28.57
Comunque, per tener traccia dei dati della macchina avevo pensato di affiancare all'applicativo in file dat criptato con i dati e offuscare il codice dell'applicazione che effettuerà le opportune verifiche circa la possibile o meno registrazione.
Non ho ancora capito al 100% se la fai in linea o no, comunque mi sembra di capire che sei offline quindi tieni conto che l'offuscamento è solo una parte della risoluzione: ripetendomi, devi considerare la possibilità che il dbase venga cancellato o salvato prima di effetture la registrazione e porre rimedio a queste eventualità.

mi chiedevo se gli id della Motherboard e del hd sono assoulutamente univoci, nel senso che non possono esistere due Motherboards o hd con lo stesso ID?!?
Per mia esperienza, ogni produttore ha una sua codifica alfanumerica (spesso viene inserita la famiglia del prodotto), ma se vuoi essere sicuro al 100% basta abbinarlo alla stringa del produttore che con le WMI di Windows è sempre identificabile.
Se il tutto (per assurdo) risultasse troppo lungo in termini di record da registrare, fondi, calcoli MD5 o qualsiasi altra codifica di controllo e salvi quella come riferimento.

Questo è il sorgente AutoIt che restituisce tutti i dadi relativi agli HDs, il porting in Java è cosa tua ... ;)

---------------------------
; Generated by AutoIt ScriptOMatic

$wbemFlagReturnImmediately = 0x10
$wbemFlagForwardOnly = 0x20
$colItems = ""
$strComputer = "localhost"

$OutputTitle = ""
$Output = ""
$OutputTitle &= "Computer: " & $strComputer & @CRLF
$OutputTitle &= "==========================================" & @CRLF
$objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\root\CIMV2")
$colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_DiskDrive", "WQL", _
$wbemFlagReturnImmediately + $wbemFlagForwardOnly)

If IsObj($colItems) then
Local $Object_Flag = 0
For $objItem In $colItems
$Object_Flag = 1
$Output &= "Availability: " & $objItem.Availability & @CRLF
$Output &= "BytesPerSector: " & $objItem.BytesPerSector & @CRLF
$strCapabilities = $objItem.Capabilities(0)
$Output &= "Capabilities: " & $strCapabilities & @CRLF
$strCapabilityDescriptions = $objItem.CapabilityDescriptions(0)
$Output &= "CapabilityDescriptions: " & $strCapabilityDescriptions & @CRLF
$Output &= "Caption: " & $objItem.Caption & @CRLF
$Output &= "CompressionMethod: " & $objItem.CompressionMethod & @CRLF
$Output &= "ConfigManagerErrorCode: " & $objItem.ConfigManagerErrorCode & @CRLF
$Output &= "ConfigManagerUserConfig: " & $objItem.ConfigManagerUserConfig & @CRLF
$Output &= "CreationClassName: " & $objItem.CreationClassName & @CRLF
$Output &= "DefaultBlockSize: " & $objItem.DefaultBlockSize & @CRLF
$Output &= "Description: " & $objItem.Description & @CRLF
$Output &= "DeviceID: " & $objItem.DeviceID & @CRLF
$Output &= "ErrorCleared: " & $objItem.ErrorCleared & @CRLF
$Output &= "ErrorDescription: " & $objItem.ErrorDescription & @CRLF
$Output &= "ErrorMethodology: " & $objItem.ErrorMethodology & @CRLF
$Output &= "FirmwareRevision: " & $objItem.FirmwareRevision & @CRLF
$Output &= "Index: " & $objItem.Index & @CRLF
$Output &= "InstallDate: " & WMIDateStringToDate($objItem.InstallDate) & @CRLF
$Output &= "InterfaceType: " & $objItem.InterfaceType & @CRLF
$Output &= "LastErrorCode: " & $objItem.LastErrorCode & @CRLF
$Output &= "Manufacturer: " & $objItem.Manufacturer & @CRLF
$Output &= "MaxBlockSize: " & $objItem.MaxBlockSize & @CRLF
$Output &= "MaxMediaSize: " & $objItem.MaxMediaSize & @CRLF
$Output &= "MediaLoaded: " & $objItem.MediaLoaded & @CRLF
$Output &= "MediaType: " & $objItem.MediaType & @CRLF
$Output &= "MinBlockSize: " & $objItem.MinBlockSize & @CRLF
$Output &= "Model: " & $objItem.Model & @CRLF
$Output &= "Name: " & $objItem.Name & @CRLF
$Output &= "NeedsCleaning: " & $objItem.NeedsCleaning & @CRLF
$Output &= "NumberOfMediaSupported: " & $objItem.NumberOfMediaSupported & @CRLF
$Output &= "Partitions: " & $objItem.Partitions & @CRLF
$Output &= "PNPDeviceID: " & $objItem.PNPDeviceID & @CRLF
$strPowerManagementCapabilities = $objItem.PowerManagementCapabilities(0)
$Output &= "PowerManagementCapabilities: " & $strPowerManagementCapabilities & @CRLF
$Output &= "PowerManagementSupported: " & $objItem.PowerManagementSupported & @CRLF
$Output &= "SCSIBus: " & $objItem.SCSIBus & @CRLF
$Output &= "SCSILogicalUnit: " & $objItem.SCSILogicalUnit & @CRLF
$Output &= "SCSIPort: " & $objItem.SCSIPort & @CRLF
$Output &= "SCSITargetId: " & $objItem.SCSITargetId & @CRLF
$Output &= "SectorsPerTrack: " & $objItem.SectorsPerTrack & @CRLF
$Output &= "SerialNumber: " & $objItem.SerialNumber & @CRLF
$Output &= "Signature: " & $objItem.Signature & @CRLF
$Output &= "Size: " & $objItem.Size & @CRLF
$Output &= "Status: " & $objItem.Status & @CRLF
$Output &= "StatusInfo: " & $objItem.StatusInfo & @CRLF
$Output &= "SystemCreationClassName: " & $objItem.SystemCreationClassName & @CRLF
$Output &= "SystemName: " & $objItem.SystemName & @CRLF
$Output &= "TotalCylinders: " & $objItem.TotalCylinders & @CRLF
$Output &= "TotalHeads: " & $objItem.TotalHeads & @CRLF
$Output &= "TotalSectors: " & $objItem.TotalSectors & @CRLF
$Output &= "TotalTracks: " & $objItem.TotalTracks & @CRLF
$Output &= "TracksPerCylinder: " & $objItem.TracksPerCylinder & @CRLF
if Msgbox(1,"WMI Output",$Output) = 2 then ExitLoop
$Output=""
Next
If $Object_Flag = 0 Then Msgbox(1,"WMI Output",$OutputTitle)
Else
Msgbox(0,"WMI Output","No WMI Objects Found for class: " & "Win32_DiskDrive" )
Endif


Func WMIDateStringToDate($dtmDate)
Return (StringMid($dtmDate, 5, 2) & "/" & _
StringMid($dtmDate, 7, 2) & "/" & StringLeft($dtmDate, 4) _
& " " & StringMid($dtmDate, 9, 2) & ":" & StringMid($dtmDate, 11, 2) & ":" & StringMid($dtmDate,13, 2))
EndFunc

RunDLL
16-07-2012, 15.51.01
Il MAC Address non lo vedo bene, non tanto perchè la scheda di rete può essere sostituita il che comunque porterebba il programma a non funzionare ed il nostro amico vuole che non sia eseguito più volte, ma perchè si potrebbero aggiungere più schede di rete e quindi eseguito più volte.
Per quanto riguarda il firmware dell'hard disk potrebbe essere la stessa cosa avendo vari hard disk.
L'unica cosa, a mio giudizio, è identificare la scheda madre.