Bonjour à tous. J'ai developpé une application java et j'aimerais la proteger par une licence qui doit être renouvellé chaque année. Comment je peux faire cela?
Merci d'avance.
Version imprimable
Bonjour à tous. J'ai developpé une application java et j'aimerais la proteger par une licence qui doit être renouvellé chaque année. Comment je peux faire cela?
Merci d'avance.
En faisant en sorte que ton application ne marche qu'avec un accès Internet, et qu'elle doive se connecter à ton serveur pour marcher (et que ton serveur fasse un travail utile de sorte que modifier l'application ne permette pas de se passer du serveur.)
Le serveur connaît donc l'ensemble des licences valides, et si une application essaie de tourner sans licence ou avec une licence invalide ou expirée, le serveur refuse de lui répondre et elle ne marche pas.
Il y a de multiples possibilités. Tout dépend du temps, de l'argent et du matériel que tu souhaites y consacrer.
Une autre possibilité : le logiciel vérifie la date système. Si c'est plus d'un an après le début de licence, il s'arrête.
Tu vas me dire qu'il suffit de modifier l'heure du PC pour que le logiciel fonctionne. Et c'est là que mes deux premières phrases prennent tout leur sens ;-)
Sache seulement ceci : quelque soit la solution choisie, il y aura toujours une méthode pour contourner la licence. Elle demandera du temps et/ou de l'argent et/ou du matériel de manière plus ou moins importante, mais ce sera toujours possible.
Tout l'exercice consiste à ce que toi, tu dépenses assez de temps/argent/matériel pour que ce ne soit pas très rentable pour le cracker et qu'il préfère acheter ta licence.
Ma méthode est certes très contraignante, mais avec elle, la seule solution de contournement est de refaire l'application soi-même au lieu de prendre une licence.
Les autres méthodes, ce qui est gênant n'est pas que ce soit possible, mais que ce soit facile. L'élégance de Java a un prix, ce prix est qu'il est facile de modifier sa structure et de patcher les programmes faits avec. Il existe quelques systèmes visant à "protéger" des programmes Java, mais ou bien ce qu'ils protègent est sans intérêt, ou bien ils ne sont pas assez nombreux et il y a des méthodes connues pour contourner chacun d'entre eux.
De plus c'est une application pour une entreprise et les états porte le nom de la structure. donc je veux un système juste pour la verification de la licence en fonction de la date.
Si c'est pour un truc aussi simple que ça, c'est d'un niveau débutant. Je ne pense pas que tu trouveras une bibliothèque qui s'en occupe à ta place.
La seule chose à décider, c'est où est enregistrée la date d'expiration de la licence. C'est une décision qui te concerne toi et que personne ne prendra à ta place.
Au bout de quelques heures de recherche j'ai entendu parlé d'un principe que je voudrais implémenter. Il est simple j'enregistre un fichier qui possède le licence qui est la concaténation d'une chaine de caractère et la date d'expiration. A chaque fois qu'un utilisateur se connecte on vérifie si la licence est toujours valide en fonction de la date courante. Le plus dur pour moi est de crypter/décrypter le fichier car pour des soucis de sécurité j'aimerais crypter le fichier avant de le stocker sur la machine serveur (machine qui contient la BD).
J'ai fait des recherches et je suis tombé sur la classe suivante:
Maintenant j'aimerais savoir:Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167 package tp; //Updates: 2004.03.23 import java.math.*; import java.security.*; import java.security.spec.*; import java.security.interfaces.*; /** * Cette classe propose des méthodes permettant de crypter et décrypter des * messages avec l'algorithme RSA. Le message doit cependant être plus petit * que KEY_SIZE. */ public class MyRSA { public final static int KEY_SIZE = 512; // [512..2048] private RSAPublicKey publicKey; private RSAPrivateKey privateKey; public MyRSA() { } public RSAPublicKey getPublicKey() { return publicKey; } public byte[] getPublicKeyInBytes() { return publicKey.getEncoded(); } public RSAPrivateKey getPrivateKey() { return privateKey; } public byte[] getPrivateKeyInBytes() { return privateKey.getEncoded(); } public void setPublicKey(RSAPublicKey publicKey) { this.publicKey = publicKey; } public void setPublicKey(byte[] publicKeyData) { try { X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(publicKeyData); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); publicKey = (RSAPublicKey)keyFactory.generatePublic(publicKeySpec); } catch (Exception e) {System.out.println(e);} } public void setPrivateKey(RSAPrivateKey privateKey) { this.privateKey = privateKey; } public void setPrivateKey(byte[] privateKeyData) { try { PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(privateKeyData); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); privateKey = (RSAPrivateKey)keyFactory.generatePrivate(privateKeySpec); } catch (Exception e) {System.out.println(e);} } public void generateKeyPair() { try { KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA"); keyPairGen.initialize(KEY_SIZE, new SecureRandom()); KeyPair kp = keyPairGen.generateKeyPair(); publicKey = (RSAPublicKey)kp.getPublic(); privateKey = (RSAPrivateKey)kp.getPrivate(); } catch (Exception e) {System.out.println(e);} } public byte[] crypt(byte[] plaintext) { return crypt(new BigInteger(addOneByte(plaintext))).toByteArray(); } public byte[] crypt(String plaintext) { return crypt(plaintext.getBytes()); } public byte[] decryptInBytes(byte[] ciphertext) { return removeOneByte(decrypt(new BigInteger(ciphertext)).toByteArray()); } public String decryptInString(byte[] ciphertext) { return new String(decryptInBytes(ciphertext)); } /** * Cette méthode permet de tester le bon fonctionnement des autres. */ public static void main(String[] args) { String plaintext = "toto"; System.out.println("plaintext = " + plaintext); MyRSA rsa = new MyRSA(); rsa.generateKeyPair(); byte[] publicKey = rsa.getPublicKeyInBytes(); byte[] privateKey = rsa.getPrivateKeyInBytes(); byte[] ciphertext = rsa.crypt(plaintext); System.out.println("ciphertext = " + new BigInteger(ciphertext)); System.out.println("Le mot crypté est: "+ciphertext.toString()); rsa.setPublicKey(publicKey); rsa.setPrivateKey(privateKey); String plaintext2 = rsa.decryptInString(ciphertext); System.out.println("plaintext2 = " + plaintext2); if (!plaintext2.equals(plaintext)) System.out.println("Error: plaintext2 != plaintext"); } private BigInteger crypt(BigInteger plaintext) { return plaintext.modPow(publicKey.getPublicExponent(), publicKey.getModulus()); } private BigInteger decrypt(BigInteger ciphertext) { return ciphertext.modPow(privateKey.getPrivateExponent(), privateKey.getModulus()); } /** * Ajoute un byte de valeur 1 au début du message afin d'éviter que ce dernier * ne corresponde pas à un nombre négatif lorsqu'il sera transformé en * BigInteger. */ private static byte[] addOneByte(byte[] input) { byte[] result = new byte[input.length+1]; result[0] = 1; for (int i = 0; i < input.length; i++) { result[i+1] = input[i]; } return result; } /** * Retire le byte ajouté par la méthode addOneByte. */ private static byte[] removeOneByte(byte[] input) { byte[] result = new byte[input.length-1]; for (int i = 0; i < result.length; i++) { result[i] = input[i+1]; } return result; } }
Comment sauvegarder une clé que j'utilise pour crypter le fichier pour le décryptage lors de la connexion d'un utilisateur?
Si le dit fichier de licence est sur le serveur, comment le lire sans utiliser le protocole ftp ou http?
Bonjour,
C'est une solution qui fonctionne bien, mais qui ne résistera pas très longtemps en java.
Comme dit plus haut, c'est une histoire de temps et d'argent pour protéger une application.
Quelle solution me proposez-vous donc?
Mais elle est très bien cette solution, si tu en es content. Elle est facile à contourner parce que ce sera toujours facile à contourner, c'est tout.
Si tu veux pas que ça le soit, je t'ai déjà dit comment faire. Tu veux pas de connexion Internet eh ben t'en auras une quand même. (Alternative : fournir une boîte USB avec chaque licence. Cette boîte contient une copie de la licence et communique avec l'appli pour vérifier qu'elle est valide, et s'occupe de faire un travail important que l'appli ne fait pas. Bref elle remplace un serveur sur Internet. C'est cher et contraignant mais ça marche.)
Pourquoi serait-elle facile à contourner? J'aimerais tout de même continuer avec mon approche pouvez-vous m'aider?
Car il suffit en java de contourner ta classe de vérification.
La conception d'une solution de licence efficace requière comme expliqué du temps et donc de l'argent.
Ce n'est pas le but du forum de fournir des solutions toutes faites.
Moi je te conseil plutôt de multiplier les vérifications partout dans ton code de manière différente et d'obfusquer un minimum.
Ca rendra le boulot plus long et donc moins intéressant pour un attaquant.
En l'occurrence, le problème est plutôt que les seules solutions qui auraient un peu d'efficacité, dénatureraient tellement l'architecture Java que ça n'aurait plus aucun intérêt d'avoir programmé l'appli en Java.
À ce niveau-là il vaut mieux programmer en C++. Il n'y a pas d'introspection, l'architecture cible est un processeur x86 abominablement sale, et déplomber ça commence à demander un certain niveau de talent.
En l'occurrence on en aurait de toute façon pas à donner...
On va pas prendre ses décisions à sa place : où faut-il planquer la clé ? Mais on en a aucune idée mon grand, où tu veux et peux !
Je ne comprends pas bien quand tu me demande de vérifier de manière moi je pensais que je devais juste lire la clé, décrypter le fichier et lire les données en faisant des tests pour savoir si la licence est valide. De plus comment je fait pour crypter le fichier je dois d'abord le lire dans une variable(String) avant de crypter?
Dans un fichier tout simple, donc.
Eh bien, pour lire/écrire du binaire, c'est InputStream / OutputStream. Dans un fichier, plus précisément FileInputStream / FileOutputStream. S'il est sur le serveur, ce n'est pas un fichier local, donc ce ne sera pas avec les FileTruc. Tout dépendra du protocole utilisé pour dialoguer avec le serveur.
En supposant qu'il n'y aie qu'un seul code. On peux aller dans des chemins plus ou moins complexe:
avoir une partie de la clé décodée qui sert de base à certains des calculs que fait le serveur: du coup, il ne suffit pas de supprimer les check, il faut simuler tout le retour de décodage. Avoir le décodage non pas dans une méthode, mais via un ou plusieurs bout de code copié/collé partout dans le code. Du coup pour faire sauter le décodage faut aller trouver tous les endroit dans le code où t'as fait ce putain de copier/coller, probablement en le mélangeant avec du code buisness. Mais ce sera une chierie pour toi à maintenir.
Si le serveur a une connexion internet tu pourrais rajouter du code qui, occasionellement, se connecte à un serveur central puis te signaler qu'un serveur tourne avec ta clé.
Maintenant, bien qu'il ne faille pas donner la solution tout cuite aux pirate, si ton logiciel doit tourner dans une entreprise et qu'il sert à son buisness, l'entreprise n'ira pas courir le risque, en général, de reposer sur une application qui peut pêter demain à cause du crack. Le risque de piratage est plus faible. On trouve sans problème des cracks pour la pluspart des produits microsoft. Et pourtant, les entreprises achetent toujours autant de licence sharepoint ou sqlserver. Le jeu n'en vaut pas la chandelle. Pour économiser 50.000 euros de licence, risque de perdre des centaines de milliers d'euros en données perdues et jours de chomage le jour où ça pêtera....
Il suffit d'utiliser un outil comme JAD et de "décompiler" les classes.
Ensuite, tu n'as plus qu'à supprimer le bout de code qui fait le test de licence ou l'appelle et tu as "déplombé" l'application.
Bref, c'est très facile.
La solution d'un serveur est de loin la meilleure (typiquement une architecture client/serveur), le client étant fait pour afficher les résultats uniquement. L'inconvénient étant d'obliger le client d'avoir une connexion.
Disons que c'est un peu comme la guerre.
Il y a des armes de base: la copie pure et dure de ton programme pour pas payer
Il y a les gilets pare-balle: une licence et une simple vérification de sa date
Il y a les armes lourdes, contre lesquels le gilet ne sert à rien: supprimer le check (décompilation ou encore plus facile maintenant, utiliser l'aop pour faire de l'injection de methode), fabriquer une fausse licence
Il y a donc les véhicule blindés: verrouiller la licence avec une clé cryptographique et planquer le code, avec des obfuscateurs par exemple
Il y a les armes anti-tank: remplacer la clé cryptographique, décompiler le code en assembleur ou avec des noms de variables obscon et recompiler quand même
Il y a des contre mesures passives aux missiles anti tanks: Multiplier les nombre de vérifications dans le code, ne pas tout centraliser dans une classe, utiliser la sortie cryptographique dans des calculs du programmes, rajouter des tests supplémentaire pour s'assurer que les classes n'ont pas été modifiées, refuser aléatoirement les fausses clés pour ne pas pouvoir savoir si on a réussi du premier coup mais plutot avoir un truc qui crashe après 2 semaines, ...
Il y a les missiles anti tanks à double charge pour contrer les contre mesures: ...
Il y a les contre mesures actives: ....
....
C'est une escalade sans fin. Le tout est d'avoir une idée de
Toi tu es prêt à aller jusque où?
L'adversaire veux bien aller jusqu'où? On ne protège pas de la même manière le dernier photoshop piraté à des millions d'exemplaires qu'on ne protège la dernière version de github enterprise qui n'intéresse que quelques milliers de clients à travers le monde
Ce n'est pas parce que la protection absolue n'existe pas qu'il est inutile de mettre un minimum de protection. A toi de voir ce qui est faisable, d'utiliser ton imagination. Le b-a-ba je dirais, c'est au minimum:
De décoder la licence avec une clé publique pour vérifier son contenu
De garder bien au chaud chez toi la clé privée
D'éviter qu'il soit possible de facilement remplacer la clé publique dans ton programme
Ok merci pour vos reponses. Je représsisse mes attentes mon problèmes ce n'est pas que craigne que quelqu'un puyisse copier mon logiciel d'une entreprise AZ pour une entreprise B car les états portent le nom de l'entreprise de plus l'application ne sert à rien sans le serveur. Je veux bien continuer avec mon approche qui vas donc stocker le fichier de licence sur le serveur et également la clé pour décrypter. maintenant comment les lire et avec quel protocole et comment faire? voilà à peu près mes préaucupations.
Comment les lire: comme n'importe quel fichier
Comment la décrypter: Tu peux trouver pas mal de documentation sur ce forum à propos de la cryptographie assymétrique. Java possède tout ce qu'il faut, faut juste passer les bon paramètres.
ben une connexion internet entre l'application déployée chez le client et un serveur de licences central dans ta société. :)
Oui on a bien compris, tu ne part pas sur l'option d'un serveur décentraliser qui gère les licences et fait un travail utile. Je crois que c'est toi qui n'a pas bien compris. T'as pas besoin d'un serveur distant nécessairement pour vérifier la licence et gérer la clé cryptographique. L'option du serveur distant, c'était une solution qui permettait d'éviter le crack. J'ai bien compris, on ne part pas dans cette direction. Donc maintenant, qu'est-ce qui te coince?
Bon je m'explique un peut mieux je mets la clé sur un sereur distant pour ne pas l'aoir sur tous les postes clients idem pour la clé de décryptge. Ce que je nrrie pas à faire c'est le procédé pour lire un fichier sur une machine distante
Non mais, prenons l'état des lieux et faisons avec.
Tu as des postes client, et ton application est une application desktop sur le poste client? Si oui tu met la licence sur le poste client (dans un dossier que tu choisi), tu inclue la clé publique à ton programme, tu fais tes checks dans le programme après avoir décodé la licence avec la clé publique. Pas besoin de serveur pour tout ça.
Il n'y a pas de magie : en dehors des problématiques de ton programme, le poste client doit pouvoir contacter le serveur.
Sont-ils connectés en réseaux ?
Si aucun programme serveur ne tourne sur la machine serveur, alors tu dois installer un programme serveur. Lequel ? A toi de choisir. Peut-être FTP par exemple ?
Ensuite ton programme doit être capable de faire une requête sur le programme serveur de la machine serveur. En Java, le protocole FTP est directement géré par l'API standard.
Bon, va falloir clarifier franchement. Tu veux protéger quoi contre la copie?
L'application que tu déploie sur les postes clients?
Le serveur que tu installe chez le client?
Les deux?
Aussi, corrige cette lettre "v" qui ne marche plus sur ton clavier, tes messages sont très durs à lire ;)