2010-12-08 5 views
0

J'essaie de comparer des tableaux de 2 octets.Comparaison des tableaux d'octets

tableau d'octets 1 est un tableau contenant les 3 derniers octets d'un hachage SHA1:

private static byte[] sha1SsidGetBytes(byte[] sha1) 
    { 
    return new byte[] {sha1[17], sha1[18], sha1[19]}; 
    } 

tableau d'octets 2 est un tableau qui je remplis avec 3 octets provenant d'une chaîne hexadécimale:

private static byte[] ssidGetBytes(String ssid) 
    { 
    BigInteger ssidBigInt = new BigInteger(ssid, 16); 

    return ssidBigInt.toByteArray(); 
    } 

Comment est-il possible que cette comparaison:

if (Arrays.equals(ssidBytes, sha1SsidGetBytes(snSha1))) 
    { 
    } 

fonctionne la plupart du temps, mais parfois pas t. Commande d'octets?

par exemple. pour "6451E6" (chaîne hexadécimale) ça marche bien, pour "ABED74" ça ne l'est pas ...

+1

Avez-vous regardé ce que vos tableaux d'octets contiennent dans le débogueur? Est-ce que vous rencontrez des problèmes avec des octets signés? –

+0

Comment puis-je voir s'ils sont signés? – tersmitten

Répondre

1

Votre approche de l'analyse d'une chaîne hexagonale via BigInteger est imparfaite, fondamentalement. Par exemple, new BigInteger("ABED74").toByteArray() renvoie un tableau de octets, et non trois. Alors que vous pouvez pirater autour de cela, vous êtes fondamentalement en train d'essayer de faire quelque chose impliquant des valeurs BigInteger ... vous essayez juste d'analyser hex.

Je vous suggère d'utiliser la bibliothèque Apache Codec pour faire l'analyse syntaxique:

byte[] array = (byte[]) new Hex().decode(text); 

(L'API Apache Codec laisse à désirer, mais il fonctionne.)

+0

Alors ce serait le problème je suppose? Existe-t-il un autre moyen d'analyser une chaîne hexadécimale (longueur 6) dans un tableau de 3 octets? – tersmitten

+2

@tersmitten: Oui, comme je l'ai dit: utilisez quelque chose conçu pour analyser une chaîne hexadécimale en octets, au lieu de quelque chose qui arrive à le faire afin d'accomplir une tâche plus grande. Vous n'avez pas besoin d'utiliser une bibliothèque tierce, bien sûr: il est facile d'écrire une méthode pour analyser un hex si vous le souhaitez. –

+0

Vous avez probablement raison mais je pensais que c'était une manière infaillible ... – tersmitten

3

Le problème est assez évident si vous essayez ceci:

BigInteger b1 = new BigInteger("6451E6", 16); 
BigInteger b2 = new BigInteger("ABED74", 16); 

System.out.println(b1.toByteArray().length); 
System.out.println(b2.toByteArray().length); 

Plus précisément, ABED74 crée un BigInteger dont tableau d'octets est de 4 octets - si bien sûr, il ne va pas être égal à tout Thr ee tableau d'octets.

La solution simple consiste à modifier l'instruction de retour dans ssidGetBytes de

return ssidBigInt.toByteArray(); 

à

byte[] ba = ssidBigInt.toByteArray(); 
return new byte[] { ba[ba.length - 3], ba[ba.length - 2], ba[ba.length - 1] }; 
+0

Bingo. Il faut ajouter que la méthode toByteArray() est destinée (principalement) à produire des entrées compatibles avec le constructeur BigInteger (byte []). On pourrait dire que ** ce ** codage en octets est ** unidirectionnel ** par rapport à l'entrée String du constructeur: La représentation byte [] de la chaîne d'entrée n'est pas forcément la même que la représentation byte [] de le BigInteger créé à partir de la chaîne (puisque le dernier pourrait probablement porter des informations supplémentaires comme la magnitude.) –

1

Du de javadoc (mine d'importance):

http://download.oracle.com/javase/1.5.0/docs/api/java/math/BigInteger.html#toByteArray%28%29

Renvoie un tableau d'octets contenant la représentation deux-complément de ce BigInteger. Le tableau d'octets sera en octets big-endian: l'octet significatif le plus significatif est . Le tableau contiendra le nombre minimum d'octets requis pour représentent ce BigInteger, y compris au moins un bit de signe, qui est (ceil ((this.bitLength() + 1)/8)). (Cette représentation est compatible avec le constructeur (byte []).)

Il y a beaucoup de calculs en cours dans la méthode ByteInteger (String, radix) du constructeur que vous utilisez, ce qui ne garantit pas le BigInteger construit produira un tableau d'octets (via son toByteArray()) comparable au résultat du codage getBytes() d'une chaîne.

La sortie de toByteArray() est destinée à être utilisée (principalement) en entrée du constructeur (byte []) de BigInteger. Il ne garantit aucune utilisation autre que celles-ci.

Regardez-le comme ceci: la sortie de toByteArray() est la représentation en octets de l'objet BigInteger et tout ce qu'il contient incluant des attributs internes comme magnitude. Ces attributs n'existent pas dans la chaîne d'entrée, mais sont calculés pendant la construction de l'objet BitInteger.

Cela sera incompatible avec la représentation en octets de la chaîne d'entrée qui porte uniquement la valeur numérique initiale avec laquelle créer un BigInteger.