C/C++ [RSA] Chiffrement mot de passe

A

Anonymous

Invité
#1
Salut à tous =)

Je viens vers vous aujourd'hui car je me suis lancé depuis quelques jours dans un bot socket D2 et j'aimerai savoir si vous saviez comment se passe le chiffrement RSA. J'ai encore un peu de mal à comprendre bien me repérer dans les .as (surtout avec sothink qu'arrive a en lire 1 sur 2 x) ) donc j'ai pas accès à tout, et après plusieurs recherche sur le forum, l'histoire des deux clés et de la vérification me parait toujours flou :?

Pour l'instant je stock la salt et le vector d'int mais je ne sais pas vraiment quoi en faire :|
Autre chose, par rapport à la version, recoder une classe est vraiment utile ? Si c'est le seul endroit où l'on en a besoin, mettre les octets en dur est pas une mauvaise idée :twisted:

Voilà ^^
 
A

Anonymous

Invité
#2
Pour le fonctionnement du login, ça a déjà été expliqué sur des topics récemment.

Pour analyser le code je te déconseille sothink, utilise plutot JPEXS qui fonctionne bien mieux, qui est gratuit et qui est fréquemment mis à jour.

Envoyer des bytes "en dur" est une très, très, très, très très mauvaise idée, car tu vas te compliquer la vie inutilement quand il faudra mettre à jour le bot ou le débugger si quelque chose ne fonctionne plus.
 
A

Anonymous

Invité
#3
En l’occurrence, pour la mise a jour, ça ne change rien étant donné qu'au lieu de changer des paramètres envoyer à une classe qui te servira une fois dans tout le programme, tu ne fais que changer directement les octets. Par exemple, je fais un writeByte(); x8 (les 6 params de version + install + techno), je changerai juste les valeurs que je met dans les writeBytes s'il y a une MAJ.
Je ne fais ça que parce que je suis sûr que la classe version ne sert qu'ici (ce qui fais d'elle une classe inutile a mon gout, autant directement gérer ça), après, peut-être que je me trompe :o

Sinon, pour le fonctionnement du rsa, j'avoue que je me perds un peu vu que je n'ai pas vraiment accès au .as et que les infos sont répartis sur plusieurs topic différents, ce serait sympa d'avoir un tuto ou un récapitulatif dessus =)

Merci de ta réponse ^^

PS : merci pour JPEXS, très utile :D
 
A

Anonymous

Invité
#4
Oui tu te trompe complètement sur le premier point. La version est un type qui est en effet exploité par plusieurs messages réseau, si tu souhaites maintenir du code sale avec des doublons libre à toi. De plus cet attitude au minimat va forcemment se retourner contre toi à un moment ou à un autre, lorsqu'il faudra maintenir ou débugger le code. Créer un bot fonctionnel est un exercice difficile qui ne laisse pas la place à du code sale et non réfléchi, et d'ailleurs c'est valable pour n'importe quel programme un peu complexe. Cette attitude est vraiment une très mauvaise habitude en programmation, et il n'y a pas que moi qui te le dira.

Enfin bref je ne vais pas plus essayer de te convaincre, après tout j'en ai à peu près rien à faire :>

Pour le fonctionnement du RSA, tu as toutes les clefs sur ce forum pour y parvenir comme je te l'ai déjà dit. Utilises le moteur de recherche ...

En revanche tu postes dans la section C++, si tu utilises ce langage pour le RSA tu auras besoin de la librairie openssl. Tu trouveras de la doc sur le net pour exploiter le chiffrement.
 
A

Anonymous

Invité
#5
Par rapport a la version, si elle est utilisée une fois de plus, je te l'accorde, autrement, encore une fois, seule la "lisibilité" défend la classe que tu utilises une seule fois dans ton code, j'ai pas mal de pratique derrière moi, notamment en c / c++, je préfère clairement 8 writebytes bien commentés a une classe. Après, tu me dis que j'en aurai besoin à d'autres moment, je la code, sinon, ça se vaut très largement, notamment grâce au fait que ces 8 writebytes se trouvent eux mêmes dans une méthodes de 10 - 12 lignes elle même dans une classe spécifique au message (dans le fin fond du code). Encore une fois, c'est une attitude née du fait que mon manque d'expérience du protocole D2 m'a poussé à croire que ce serait unique dans le programme.

Pour moi, du code sale non redondant bien encapsulé convertissant deux fichiers en 8 lignes se justifie. En l’occurrence ici, ce n'est pas le cas => je recommence, et il semble que comme tu le dise, un bot doit être plus rigoureusement codé que je ne le pensais, je ferai plus attention à l'avenir =)

Merci ^^

PS : Parler de son code avec d'autres personne pour connaître son point de vu, perso, ça m'intéresse =)

EDIT :
Après quelques recherches, j'ai trouvé deux trois choses intéressantes mais j'aimerai avoir confirmation par rapport au message 4.
En regardant le .as, on trouve ça :
Code:
public function serializeAs_IdentificationMessage(param1:IDataOutput) : void {
         var _loc2_:uint = 0;
         _loc2_=BooleanByteWrapper.setFlag(_loc2_,0,this.autoconnect);
         _loc2_=BooleanByteWrapper.setFlag(_loc2_,1,this.useCertificate);
         _loc2_=BooleanByteWrapper.setFlag(_loc2_,2,this.useLoginToken);
         param1.writeByte(_loc2_);
         this.version.serializeAs_VersionExtended(param1);
         param1.writeUTF(this.lang);
         param1.writeShort(this.credentials.length);
         var _loc3_:uint = 0;
         while(_loc3_ < this.credentials.length)
         {
            param1.writeByte(this.credentials[_loc3_]);
            _loc3_++;
         }
         param1.writeShort(this.serverId);
         param1.writeDouble(this.sessionOptionalSalt);
         return;
      }
Après, je regarde mon message :
(00) (02 0d 04 00 01 26 23 01) (00 01 01) (00 02 66 72) (jusqu'à la langue)
On retrouve le boolean, la version, ???, la langue. Mais que se trouve t-il entre la version et la langue ?

Autre chose, a quoi correspondent useCertificate et useLoginToken ?
Par rapport a cipherRsa, param1 et param2 correspondent ils bien aux idents ? TrustCertificatate est à traduire uniquement dans le cas où useCertificate est valide non ? useCertificate servant à mon avis à valider l'ordinateur via certificat, faut au moins l'utiliser au premier lancement du bot non ?

Beaucoup de question :D
 
A

Anonymous

Invité
#6
La méthode "writeUTF" écrit d'abord un short de la longueur de la chaine de caractère, puis celle-ci.
Ce qui doit se trouver entre version de langue doit à priori être la longueur de la langue.

useCertificate
useLoginToken
Sont employés dans le cas d'un login non conventionnel par certificat ou par token. Ce n'est pas utilisé par les clients normaux, mais probablement par les admins dofus, ou par les développeurs. Tu n'a pas à t'en soucier, passe juste ces bool en false et dans cipherRSA ne prend pas en compte le certificate.
 
A

Anonymous

Invité
#7
Pour la langue, on a (00 02) (66 72) (taille : 2 + "fr") les 00 01 01 ne semblent pas être la taille :/
Pour cypherRsa, je me demandais, il faut recoder tout le .verify ou ya un truc dans l'openssl qui le fait tout seul ? S'il faut le recoder, a t-on besoin de recoder tout RSAkey et compagnie ou juste le _decrypt suffit ?
Merci beaucoup pour tes conseils =)
 
A

Anonymous

Invité
#8
Il y a une fonction toute faite.
 
A

Anonymous

Invité
#9
fiouuu je vais regarder vers openssl, sinon, par rapport aux 3 bytes inconnus, je regarderai des sources sur le fofo, et pour le _decrypt, je commencais un peu à me perdre dans le code, je vais regarder dans openssl pour voir ce qui pourrait me faire le café =) Je posterai plus tard si je trouve toutes les infos nécessaires ^^

Encore merci Munrek :D

EDIT :
Voilà, j'avance avec openssl tranquillement, et j'ai trouvé plusieurs chose intéressantes, en espérant ne pas être complètement à côté de la plaque.
Je recupère la verifKey dans 305.bin à l'aide d'un fopen puis je PEM_read_RSA_PUBKEY, jusque là, pas de soucis, et j'arrive au verify. Il existe une fonction RSA_verify, remplissant la "signature" (ce que l'on doit à mon avis encoder en base64 non ?). Malheureusement, pour ce verify, j'ai besoin de certaines variables initialiser par RSA_sign utilisant une clé privée :/ Me serais-je trompé ?

Mon petit morceau de code :

Code:
void                  serializeAs_IdentificationMessage(__attribute__((unused))char *salt,
                                                          std::vector<int> &key,
                                                          Writter &writter)
  {
    RSA         *rsaKey;
    FILE        *keyInFile;
    unsigned char *keyByte;
    int         i;

    i = 0;
    if ((keyByte = (unsigned char *)malloc(sizeof(unsigned char *) * key.size())) == NULL)
      {
        std::cerr << "MALLOC FAILED" << std::endl;
        exit (0);
      }
    for (std::vector<int>::iterator it = key.begin(); it != key.end(); ++it)
      {
        keyByte[i] = *it;
        ++i;
      }
    writter.writeByte(0); // BOOLEAN à traiter correctement plus tard.......
    this->_version.serializeAs_versionExtended(writter);
    /* POURQUOI */
    writter.writeByte(0);
    writter.writeByte(1);
    writter.writeByte(1);
    /* ? */
    writter.writeString(2, "fr");
    if ((keyInFile = fopen("305.bin", "r")) == NULL)
      {
        std::cerr << "FOPEN FAILED" << std::endl;
        exit (0);
      }
    if ((rsaKey = PEM_read_RSA_PUBKEY(keyInFile, NULL, NULL, NULL)) == NULL)
      {
        std::cerr << "READ KEY FAILED" << std::endl;
        printf("[-] Erreur Public Key : %s\n", ERR_error_string(ERR_get_error(), NULL));
        fclose(keyInFile);
        exit (0);
      }
    if (RSA_verify(/*    Et la, ca bloque :/    */) == 0)
      {
        std::cerr << "VERIFY FAILED" << std::endl;
        fclose(keyInFile);
        exit (0);
      }
    writter.sendServer(this->_protocolId);
    fclose(keyInFile);
  }
 
A

Anonymous

Invité
#10
Mon code en C++ ne me sert plus, je le met donc ici, si ça peut t'aider, j'ai bien galéré 3 jours pour arriver à ce résultat fonctionnel ...

Code libéré sous license GPL v3.
 
A

Anonymous

Invité
#11
Recoucou =)

Merci beaucoup pour tes sources, ça me crée bien un credentials de 256 impec mais malheureusement, passé cela, je recois en boucle un message 01 55 (id 85 = ActionDofus/com/ankamagames/dofus/network/types/game/actions/fight/GameActionMarkedCell.as) qui n'a rien à faire là o_O'
Voilà ma démarche :
Je crée mon credential à partir de : salt << strlen(pseudo) << pseudo << mdp;
J'appelle rsa.setLoginPublicKey(rsa.DodoPKeyDecrypt(CleRecupererDansLePacket3));
Et j'encrypt avec le rsa le credential.

Un message du client :
Code:
00 12 01 1C 00 02 0D 04 00 01 27 0E 01 00 01 01
00 02 66 72 01 00 7A 6F 4C 0A E7 35 F2 75 DA 96
3C F9 42 96 88 BD 78 E8 30 61 82 E1 EE 28 DE 39
7D 0D 24 63 E4 08 9F 13 B8 BE CF E2 52 44 98 96
D3 15 04 CD 0B 56 FB FE F9 3C FA 9E E6 0C 43 36
FF 6F 60 AA C3 DD 47 F2 92 03 0B 40 40 5C D9 0F
57 DA 93 BD 4A 62 6B B9 1E C9 4B 11 EF 19 3F 09
A4 63 AC 61 3D 1F E0 48 9B D6 5B 5F 50 A8 4F 04
D3 D4 C8 4A 39 3F 40 B6 28 2F E7 72 A2 B8 4E 2A
DE ED 32 9E D3 D8 9C E8 4E 02 1E 51 92 C2 E3 7F
79 75 60 93 C9 A9 80 24 26 FA 00 79 72 00 82 54
42 B1 1F C4 E1 8D E9 E3 6A 1E 5C 28 7C 15 F7 DE
93 01 8F 31 37 4A 3B 3B CE D5 F6 DE 45 AE 99 C4
CA CB 0C 1E 5B EB 33 85 30 36 9B 58 36 22 92 2B
DA 74 19 12 F8 F9 9E EA 89 46 33 C7 C4 CC 8F 2B
C9 2A F6 BA 4C 34 A1 E8 51 55 40 1F EE B0 DD 34
C7 FE B2 BA CB 60 90 A6 36 29 E2 8C 44 32 8C CB
23 72 65 95 2D 02 00 00 00 00 00 00 00 00 00 00
Mon message :
Code:
00 12 01 1C 00 02 0D 04 00 01 27 0E 01 00 01 01
00 02 66 72 01 00 97 09 C7 14 55 9E 6C 84 E1 40
75 B1 88 91 4C C2 4B 0B A0 B4 25 1B 8F 66 9D AE
55 B6 AA 09 C8 2D 65 AE B1 61 61 51 00 D2 E9 C7
54 03 C0 CF B9 48 03 B6 28 18 13 2A F0 6D 16 F0
60 7C 46 19 45 E6 D6 08 EF 50 45 44 4F 3D E2 8F
A2 37 50 D4 22 CF 70 4B A6 AD A2 23 94 B3 1B B7
3B 07 3B A5 67 AD 1C 9B 64 87 DC 41 5D 82 31 BD
1F E0 86 ED 70 D8 37 2B A7 FC 56 0E 02 28 13 62
AB 4D 7B 65 51 B6 27 59 9D 6A C1 EE 73 E0 38 2F
4B 52 E2 33 DC 03 F2 41 74 F8 05 66 40 EB 6F 1C
60 37 EA 54 72 D6 07 9C B4 D2 68 69 3B 85 BF 9B
4B 90 06 97 0F 74 18 A0 8F DC 5B 1F 31 FC 58 72
50 7B BE 72 9D 2E 07 08 B0 41 C0 1D B0 41 91 DB
05 18 0D AD 7E 89 B3 EC 10 1E 98 8D 46 D0 30 07
C0 97 20 BE 20 B4 BB 0E 0C CB 5F 2C 11 E9 71 BD
56 62 A0 1D 4B 64 69 DA 5A 34 17 B8 82 CA 4C 92
93 19 E5 B4 D5 22 00 00 00 00 00 00 00 00 00 00
Les idents sont potentiellement retrouvable, mais bon, juste un compte de test.

Par rapport à tes sources, les 2 strcpy que tu utilises (debut de decrypt / encrypt) peuvent faire planter étant donné que tu strcpy quelques chose que tu viens juste de malloc (non initialisé). De plus, tu malloc pour strcpy, autant utilisé un strdup =)

Cordialement ^^
 
A

Anonymous

Invité
#12
Par rapport à tes informations, tu fait le RSA correctement. Je n'ai pas le temps de pousser loin l'investigation, mais peut être que ton parser ne fonctionne pas bien, les paquets 85 n'ont rien à faire ici en effet.
 
A

Anonymous

Invité
#13
Ok ok je vais voir de mon côté je vous tiens au courrant ^^
 
A

Anonymous

Invité
#14
Connexion coupée = Paquet malformé

Ton IdentificationMessage n'est pas correct, vérifie que tu serializes tous les champs correctement, dans le bon ordre et avec le bon type.
 
A

Anonymous

Invité
#15
C'était un problème de compteur dans le writter, maitenant, je recois le packet IdentificationMessageFailed (20) reason 02 => WRONG CREDENTIALS :/ Ca viendrait de mon credentials ? (salt + strlen(pseudo) + pseudo + mdp)
 
A

Anonymous

Invité
#16
Vérifie la concatenation et l'écriture, compare un IdentificationMessage produit par ton bot et par le client avec les mêmes credentials etc ... il y a beaucoup d'erreurs possibles.
 
A

Anonymous

Invité
#17
Et l'erreur était : je faisais un << strlen(pseudo) dans mon stringstream au lieu de << (char)strlen(pseudo) ce qui mettait "10" au lieu de '10' par exemple soit en mémoire : credentials[x] = '1' ; (49) credentials[x + 1] = '0'; (48) au lieu de credentials[x] = 10; (10).

Merci Munrek pour ton DRSA, marche du tonnerre =) Je crois savoir d'où venait mon erreur, j'avais un '\n' en trop a la fin du fichier chez moi, je retenterai plus tard avec ma version et sans ce fuckin retour à la ligne !
Pour info, tu avais terminé ton bot c++ toi ?
 
A

Anonymous

Invité
#18
Non, le C++ m'a lassé pour diverses raisons, j'ai repris mon bot en langage D.
Pour plus d'infos tu peux voir mon topic : viewtopic.php?f=59&t=1346 ( particulièrement ce message : viewtopic.php?f=59&t=1346&start=10#p15393 )

Bon courage pour ton bot. Si tu comptes continuer à utiliser mon implémentation de RSA pour dofus en C++, pense qu'elle est soumise à une license GPL v3 ;)
 
Haut Bas