Conversion de Windows Phone ANID en ANID2 sur C #?

Windows Phone 7 possédait une propriété d’identification d’utilisateur anonyme appelée ANID. Windows Phone 8 a remplacé cela par ANID2. La différence est que ANID2 dépend de l’ID de l’éditeur de l’application.

Il est possible de convertir ANID en ANID2 comme le montre l’ exemple de code suivant sur MSDN. Seuls les éléments dont vous avez besoin sont l’ANID WP7 d’origine et l’ID d’éditeur (guid). Le problème est que l’exemple est en C ++. J’ai essayé de le porter en C # mais sans succès.

L’algorithme lui-même est assez simple:

var data = HMAC(ANID, publisherId) // Uses SHA-256 var result = ToBase64(data) 

Le problème est que je ne parviens pas à faire correspondre les résultats. Je me suis assuré que le C ++ fonctionne correctement en créant deux applications (WP7 et WP8), en les exécutant sur les mêmes appareils, puis en convertissant l’ANID à partir de l’application WP7 à l’aide du GUID de l’éditeur. En C ++, l’ANID2 converti et l’ANID2 du périphérique correspondent. Sur C #, l’ANID2 converti est autre chose.

Le code C # est simple:

  var anidBytes = System.Text.Encoding.UTF8.GetBytes(this.anidBox.Text); var publisherGuid = Guid.Parse(this.publisherBox.Text.ToUpper()); var macObject = new HMACSHA256(anidBytes); var hashed = macObject.ComputeHash(publisherGuid.ToByteArray()); var result = Convert.ToBase64Ssortingng(hashed); 

La version C ++ utilise quelque chose appelé CNG (Cryptography API: Next Generation). En voici un code:

 BCryptOpenAlgorithmProvider(&Algorithm, BCRYPT_SHA256_ALGORITHM, NULL, BCRYPT_ALG_HANDLE_HMAC_FLAG); BCryptGetProperty(Algorithm,BCRYPT_OBJECT_LENGTH,reinterpret_cast(&HashObjectLength),PropertyLength,&PropertyLength,0); BCryptCreateHash(Algorithm, &Hash, HashObject, HashObjectLength, pAnidId, dwAnidLength, 0); BCryptHashData(Hash, const_cast(pPublisherId), dwPublisherIdLength, 0); BCryptFinishHash(Hash, pUniqueId, GETDEVICEUNIQUEID_V1_OUTPUT, 0); 

Après quoi, le “pUniqueId” est un convertisseur en Base64 utilisant une fonction personnalisée.

Toute aide est appréciée.

Mise à jour: Visual Studio indique que anidBytes (C #) et pAnidId (C ++) (il s’agit de la chaîne ANID convertie en octets) ont tous deux une longueur de 44. Voici comment le débogueur C # signale le tableau d’octets:

Tableau d'octets C #

Et voici le débogueur C ++: Version C ++

Je ne connais pas le C ++, donc je ne sais pas si ces deux sont identiques. Ils le sont, mais le C ++ a ces caractères “\ 0” après chacun et je ne suis pas sûr que ce soit correct. Je pense que oui, la longueur dans les deux cas est de 44.

Une autre comparaison de tableau d’octets est la suivante: publisherGuid (C #) et pPublisherId (C ++) (ID d’éditeur en tant que GUID). Je pense qu’ils correspondent à nouveau. C #:

Tableau d'octets C #

C ++:

Tableau d'octets C ++

Si je regarde ensuite la sortie après que la valeur a été cryptée, je peux voir une différence:

Sur C # je récupère le résultat de ce code:

  var macObject = new HMACSHA256(anidBytes); var hashed = macObject.ComputeHash(publisherBytes); 

Et le tableau d’octets ressemble à ceci:

Résultat de cryptage C #

Sur le code C ++, si je vérifie le pUniqueId (résultat de BCryptFinishHash), je vois ceci:

Résultat de hachage C ++

La longueur semble être la même dans ces deux cas, mais le résultat n’est pas.

Sur C #, si je change le type de codage de UTF8 à Unicode, le tableau d’octets anidBytes se change en ceci:

Unicode

C’est donc identique à ce que montre le débogueur C ++. Le résultat change également, mais il diffère toujours de C ++. Voici le nouveau résultat C #:

Résultats unicode C #

C’est le bon résultat de C ++:

Résultat correct

Assurez-vous de couper le tableau d’octets ANID en deux avant de l’utiliser comme clé secrète pour le HMACSHA256. L’algorithme de conversion n’a besoin que des 44 premiers octets et non des 88. Ne me demandez pas pourquoi, mais autant que je sache, c’est un bogue dans le code C ++ utilisé lors de la conversion d’ANID en ANID2 si vous consultez l’exemple de code à l’ adresse http: / /code.msdn.microsoft.com/wpapps/ANID-to-ANID2-Converter-cc428038 – ils doivent avoir pris wchar pour caractère!

En C #, pour votre object HMACSHA256 , essayez de définir la propriété Key plutôt que de l’initialiser dans le constructeur.

 var anidBytes = System.Text.Encoding.Unicode.GetBytes(this.anidBox.Text); var macObject = new HMACSHA256(); macObject.Key = anidBytes; 

http://msdn.microsoft.com/en-us/library/9c9tf8wc.aspx indique que le constructeur insère la clé sur 64 octets.

(Je ne suis pas sûr à 100% de ce que le configurateur fait, mais cela en vaut la peine).

 public ssortingng Convert(ssortingng winPhone7Anid) { var anidAsBytes = System.Text.Encoding.Unicode.GetBytes("A=" + winPhone7Anid + "&E=f48&W=3"); var macObject = new HMACSHA256(anidAsBytes.Take(anidAsBytes.Length / 2).ToArray()); var hashedBytes = macObject.ComputeHash(new Guid("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX").ToByteArray()); return System.Convert.ToBase64Ssortingng(hashedBytes); }