Re: maj 2.9 : probleme de publicKey
bon là j'ai un peu de temps devant moi, je vais décortiquer la fonction setPublicKey(param1:Vector.<int>) : void de AuthentificationManager.as version 2.9
afin d'y voir un peu plus clair dans le fonctionnement "théorique" de la création de la publicKey "utilisable".
public function setPublicKey(param1:Vector.<int>) : void {
var _loc_2:* = new ByteArray();
var _loc_3:int = 0;
while (_loc_3 < param1.length){
_loc_2.writeByte(param1[_loc_3]);
_loc_3++;
}
_loc_2.position = 0;
var _loc_4:* = new ByteArray();
var _loc_5:* = PEM.readRSAPublicKey((new this._verifyKey() as ByteArray).readUTFBytes((new this._verifyKey() as ByteArray).length));
PEM.readRSAPublicKey((new this._verifyKey() as ByteArray).readUTFBytes((new this._verifyKey() as ByteArray).length)).verify(_loc_2, _loc_4, _loc_2.length);
this._publicKey = "-----BEGIN PUBLIC KEY-----\n" + Base64.encodeByteArray(_loc_4) + "-----END PUBLIC KEY-----";
return;
}// end function
1) Analyse des nombres (int) qui vont composer la clé publique
var _loc_2:* = new ByteArray();
var _loc_3:int = 0;
while (_loc_3 < param1.length){
_loc_2.writeByte(param1[_loc_3]);
_loc_3++;
}
_loc_2.position = 0;
Ici, c'est la partie commune aux versions 2.8 et 2.9.
Pas de problème, on parse le vecteur d'int passé en paramètre (param1) pour remplir un ByteArray (_loc_2), qui contient donc le corps de la clé "brute" en binaire.
2) Nouveau ByteArray
var _loc_4:* = new ByteArray();
On crée ensuite un nouveau ByteArray (_loc_4).
Attention, dans la v2.8, _loc_4 est une String, qui servait à contenir le corps de la clé "brute" encodé en String. C'était suffisant, il restait à ajouter le header et le footer et la publiqueKey était utilisable en l'état.
Ici, ce n'est plus le cas. _loc_4 est un ByteArray qui, semble-t-il, est destiné à recevoir le corps de la clé "purifiée", ou "vérifiée" ou "décryptée" (c'est comme on veut). On verra plus loin la "purification".
3) Création d'une RSAKey (fictive ???)
var _loc_5:* = PEM.readRSAPublicKey((new this._verifyKey() as ByteArray).readUTFBytes((new this._verifyKey() as ByteArray).length));
On crée _loc_5 qui, malgré le *, sera de type "RSAKey".
Et c'est là le premier problème : créer une RSAKey à partir de rien : ça ne marche pas, et ça donne ... rien
Car (new this._verifyKey() as ByteArray).readUTFBytes((new this._verifyKey() as ByteArray).length) est égal à "".
En effet, la chaine passée en paramètre de PEM.readRSAPublicKey(...) est celle lue dans un ByteArray vierge (de longueur 0). Ca ne donne effectivement pas grand chose ^^
Et ça soulève le second problème : l'utilisation du "this._verifyKey", cette propriété de type "Class" qui contient justement la classe AuthentificationManager__verifyKey. Cette classe, qui hérite au second degré de la classe ByteArray, n'apporte rien en plus, ni props, ni méthodes (si l'on s'en tient à sa déclaration)...
package com.ankamagames.dofus.logic.connection.managers
{
import mx.core.*;
public class AuthentificationManager__verifyKey extends ByteArrayAsset {
public function AuthentificationManager__verifyKey() {
return;
}// end function
}
}
Y aurait-il eu un problème de décompilation ? (sait-on jamais)
Bref, à ce stade, on est sensé avoir une RSAKey de "référence" dans la variable _loc_5. En réalité ce n'est pas la cas, et _loc_5 a la valeur "null" :(
4) "Purification" de la clé "brute"
PEM.readRSAPublicKey((new this._verifyKey() as ByteArray).readUTFBytes((new this._verifyKey() as ByteArray).length)).verify(_loc_2, _loc_4, _loc_2.length);
qui aurait dû être (pour justifier la création de la variable temporaire _loc_5) :
_loc_5.verify(_loc_2, _loc_4, _loc_2.length);
C'est donc ici, en théorie qu'on décrypte le corps de la clé "brute" (actuellement sous forme d'octets dans le ByteArray _loc_2) pour obtenir un corps de clé décrypté dans le ByteArray _loc_4 (toujours sous forme d'octets). Je parle de "décryptage" car la méthode "verify(...)" fait elle-même appel à la méthode "_decrypt(...) de la classe RSAKey.
La nécessité de décrypter une clé "brute" reçue par le "HelloConnectMessage" pourrait expliquer le fait que la String résultante ait (anormalement ?) gagné en longueur en passant de la 2.8 à la 2.9 (de 396 à 408 : +12 caractères).
Evidemment, puisque _loc_5 (notre RSAKey de référence) est "null", ça plante...
Mais toujours est-t-il qu'à ce moment là, on est sensé avoir _loc_4, un beau ByteArray rempli des octets d'une clé publique utilisable.
5) Finalisation de la publicKey
this._publicKey = "-----BEGIN PUBLIC KEY-----\n" + Base64.encodeByteArray(_loc_4) + "-----END PUBLIC KEY-----";
return;
Dernière étape : à partir de notre corps de clé "décrypté" dans le ByteArray _loc_4, on crée le corps de clé décrypté sous forme de chaine auquel on ajoute le footer ("-----BEGIN PUBLIC KEY-----") et le header ("-----END PUBLIC KEY-----").
On obtient (là c'est encore purement théorique, puisque je ne suis encore jamais parvenu à cette étape) la clé publique : this._publicKey, qui sert à encrypter les données sensibles de la connexion.
6) Conclusion (enfin... ouf !)
Il se peut que certaines parties de cette analyse soient incomplètes ou inexactes étant donné qu'elle sont issues de ma simple interprétation du code que je ne suis pas en mesure de faire tourner correctement.
Alors j'attends vos réactions et vos suggestions.
Et je suis sûr que beaucoup sont concernés par les problèmes que j'ai rencontrés, ou qu'ils ont déjà réussi à les solutionner ou à les contourner.
Tous les membres de ce forum ne bottent pas en MITM, il doit bien rester encore quelques bots socket traditionnels :)
Merci d'avance.
Atlantide-Le-Bavard