[Plan du site]
Vous êtes ici ---
> Le Site du Zéro
> Les tutoriels
> Non-Officiels
> Programmation
> C
> [Tuto] Initiation au cryptage
> Lecture du tutoriel
[Tuto] Initiation au cryptage
Vous vous apprêtez à lire un tutoriel rédigé par un membre de ce site. Malgré tout le soin que ce membre a pu apporter au tutoriel, nous ne pouvons pas garantir que les informations contenues sur cette page sont exactes à 100%. Merci de garder cela en tête lorsque vous lirez cette page ;o)
Il peut être utile de crypter des données, par exemple si vous faites un jeu qui enregistre les meilleurs scores et que vous ne voulez pas que les joueurs s'amusent à bidouiller le fichier pour améliorer leurs meilleurs scores. Oui, on l'a tous fait ^^.
Aujourd'hui, je vous propose donc une initiation au cryptage. C'est vraiment sommaire, les bases des bases, mais ça a le mérite d'être accessible par n'importe qui ayant des connaissances classiques en maths (en gros vous devez connaître les opérations de base. Savoir utiliser les fonctions est fortement recommandé, mais pas obligatoire).
Continuons l'exemple cité précedemment. Vous avez un jeu qui stocke les 3 meilleurs scores dans un fichier, par exemple "high_score.bla". N'importe qui éditant ce fichier avec le bloc notes peut remplacer les scores par d'autres plus glorieux. Nous allons donc CRYPTER nos données (ouais !

).
Comment que ça marche ?
Ce que nous allons faire, c'est appliquer une fonction au chiffre à stocker. Pour la théorie, nous allons donc dire que le score est représenté par la variable "score", le chiffre à stocker est la variable "stock", et la fonction y = 2X - 4.
On va donc insérer les lignes de code suivante dans le programme:
Code : C
Puis on écrit la variable stock dans le fichier.
Si le score est de 20, on aura donc stock = 2 * 20 - 4 soit 36.
Mais quand notre programme veut afficher les scores réels, il faut décrypter les données en appliquant l'inverse de la fonction: dans le cas précédent, y = (X + 4) / 2.
Si la variable à décrypter est "crypted", on aura donc:
Code : C1 | score = (crypted + 4) / 2 ;
|
Toujours avec l'exemple précédent, nous avons:
score = (36 + 4) / 2 soit 20.
Et voilà !
Enfin, le truc c'est que l'on obtient des données cryptées prévisibles; je m'explique.
Pour un score de 20, on a 36.
Pour un score de 30, on a 56.
Pour un score de 40, on a 76.
Pour un score de 50, on a 96.
En s'y penchant un peu, on devine la fonction de cryptage facilement. Même sans aller jusque là, il suffit de mettre un chiffre très grand pour avoir un score très grand. On va donc améliorer tout ça ;).
A partir de là, deux choix s'offrent à nous. Soit éviter cette proportionnalitée du cryptage, soit faire en sorte que le programme "détecte" que l'on a bidouillé le fichier.
Voilà donc comment nous allons faire.
Nous allons utiliser une fonction dont la plupart des images de son inverse soient décimales. Et notre score sera un entier. Vous avez saisi le principe ? Le programme décrypte la valeur, si elle est décimale, il détecte le bidouillage du fichier; sinon il utilise la valeur décryptée.
Cela implique donc que:
-les variables utilisées soient des double ou des float (rappelez vous, sinon l'ordinateur tronque et ça ne marchera pas

).
-que votre chiffre sous sa forme initiale soit un entier; sinon, la valeur cryptée aura beau être authentique, le programme détectera un bidouillage qui n'a pas eu lieu.
Il nous manque juste une fonction...que vous devez connaître. Et oui, nous allons utiliser la fonction
y = X².
Pensez donc à inclure la librairie math.h.
Pour crypter le chiffre, nous le mettons au carré: dans le programme, mettre l'une des deux choses suivantes:
Code : C1 | crypted = chiffre * chiffre;
|
soit
Code : C1 | crypted = pow(chiffre, 2);
|
Et pour décrypter, nous utilisons la fonction "sqrt":
Code : C1 | decrypted = sqrt(chiffre);
|
Maintenant, il faut contrôler le chiffre décrypté.
Rappelez vous, il faut que ce soit un entier. Je détaille pour ceux qui ont du mal:
Notre score est un entier. Cela veut donc dire que la racine carré de son carré sera un entier.
Par exemple: 12 est un entier, et 12² = 144. Or racine carré de 144 vaut 12, qui est un entier.
Par contre, imaginons que notre bidouilleur remplace 144 par un nombre très grand, disons 10 000. Le programme calculera la racine carré de 100 000, soit environ 316.23. Notre programme verra que le chiffre est décimal, et affichera donc "fichier de scores corrompu" ou fera ce que vous voulez (par exemple effacer le fichier de scores en tant que punition ^^).
Maintenant il nous suffit juste d'écrire le code qui contrôlera le type du chiffre décrypté. Comment va t-on faire cela ?
Souvenez vous, dans la partie 1 m@teo nous avait parlé des fonctions mathématiques. D'ailleurs, je cite:
Citation : m@teo21
Retenez quand même les fonctions floor, ceil, et pow, elles vous seront probablement utiles (même si vous ne programmez pas une calculatrice oui oui :p).
m@teo avait vu juste, nous allons utiliser la fonction floor. En effet, si le chiffre est un entier, floor(chiffre) sera égal au chiffre. Employons donc la portion de code suivant:
Code : C1
2
3
4 | if (floor(chiffre) == chiffre)
printf("OK !");
else
printf("Pas OK !");
|
Je ne vais pas commenter ce code, à votre niveau il ne me semble pas que ce soit la peine.
Voilà, c'est fini sur la théorie. La dernière partie va parler (très brièvement) des limites de cette méthode.
La méthode que nous venons de voir à l'avantage d'être simple d'accés, mais le défaut d'être assez limitée.
Notez que cependant, pour des Zér0s comme nous, ce n'est pas vraiment la peine de chiffrer nos données avec les même méthodes que la CIA

.
Premier défaut: ça ne marchera pas avec des nombres négatifs pour une raison toute bête:
Si vous mettez votre nombre négatif au carré, puis que vous calculez sa racine carré, vous aurez la valeur absolue du chiffre. Exemple: -13² vaut 169, et racine carré de 169 vaut 13. Votre chiffre décrypté ne sera donc pas le même que le chiffre initial.
Enfin, d'une manière générale on ne se sert pas trop des négatifs, surtout dans les scores d'un jeu.
Second défaut: On peut facilement deviner la méthode de cryptage soit en extrapolant sur la fonction de cryptage, soit à l'aide d'un désassembleur.
Gné ?
Bon mon but n'est ni de vous donner des cours de maths ni de vous expliquer comment fonctionne un désassembleur (parce qu'au passage il faudrait que je vous explique l'assembleur, ce qui prend plusieurs années à maîtriser, et que moi même je ne maîtrise pas

). Cependant, je vais vous détailler rapidement ces deux méthodes.
1) Extrapolation d'une fonction
En gros, on récupère pleins de valeurs cryptées et leur équivalent non crypté. On représente les points sur un système de coordonnées cartésien, et on essaye de voir si cela s'apparente à une fonction que l'on connaît. Avec un peu d'expérience mathématique (et suivant la simplicité de la fonction

), on retrouve facilement. Et le tour est joué.
2) Le désassembleur
Pour les fonctions plus complexes, sur lesquelles on ne peut pas extrapoler, on utilise un désassembleur.
Re-gné ?
Bon, un désassembleur sert à désassembler un programme, c'est à dire récupérer le code d'un programme en assembleur.
Bref, un désassembleur nous donne le code en assembleur d'un fichier exécutable. Pour quelqu'un qui maîtrise parfaitement l'assembleur, c'est comme voir le code source de votre programme. Rassurez vous, maîtriser l'assembleur, je le repète, prend plusieurs années (dans le meilleur des cas)^^.
Sans en arriver à de tels extrêmes, il est possible (mais bien au delà du niveau d'un zér0 moyen), de voir ce qui se passe dans le processeur lors de l'éxécution d'un programme.
Voilà, c'était une initiation vraiment basique, à un niveau plus élevé on ne se sert pas de ça, mais pour des Zér0s qui font des programmes amateurs qui ne dépasseront pas (pour l'instant) un cercle restreint d'internautes, ça reste convenable.
Tiens, et si je faisais un tuto pour le niveau supérieur ?
License