Windows Phone ANID в ANID2 преобразование на C #?

В Windows Phone 7 было свойство идентификатора анонимного пользователя ANID. Windows Phone 8 заменил это на ANID2. Разница в том, что ANID2 зависит от идентификатора издателя приложения.

Есть возможность конвертировать ANID в ANID2 как следующий пример кода на MSDN показывает. Единственное, что вам нужно, это оригинальный WP7 ANID и идентификатор издателя (guid). Проблема в том, что пример на C ++. Я пытался перенести его на C #, но безуспешно.

Сам алгоритм довольно прост:

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

Проблема в том, что я не могу получить результаты матча. Я убедился, что C ++ работает правильно, создав два приложения (WP7 и WP8), запустив их на одних и тех же устройствах, а затем преобразовав ANID из приложения WP7 с помощью GUID издателя. На C ++ преобразованные ANID2 и ANID2 с устройства совпадают. На C # конвертированный ANID2 — это нечто другое.

Код на C # прост:

        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.ToBase64String(hashed);

Версия C ++ использует нечто, называемое CNG (Cryptography API: Next Generation). Вот некоторый код из этого:

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

После чего «pUniqueId» конвертируется в Base64 с использованием некоторой пользовательской встроенной функции.

Любая помощь приветствуется.

Обновить:
Visual Studio сообщает, что anidBytes (C #) и pAnidId (C ++) (это строка ANID, преобразованная в байты) имеют длину 44. Вот как отладчик C # сообщает байтовый массив:

C # байтовый массив

А вот и отладчик C ++:
Версия C ++

Я не знаю C ++, поэтому я не уверен, идентичны ли эти два. Они есть, но C ++ имеет эти символы ‘\ 0’ после каждого, и я не уверен, что это нормально. Я думаю, что так, поскольку длина в обоих случаях сообщается как 44.

Другим сравнением байтового массива является publisherGuid (C #) и pPublisherId (C ++) (идентификатор издателя как GUID). Я думаю, что они снова совпадают. C #:

C # байтовый массив

C ++:

C ++ байтовый массив

Если я тогда посмотрю на вывод после того, как значение было зашифровано, я вижу разницу:

На C # я получаю вывод из этого кода:

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

И массив байтов выглядит так:

C # склеп результат

В коде C ++, если я проверяю pUniqueId (результат BCryptFinishHash), я вижу это:

C ++ хеш-результат

Длина в обоих случаях одинакова, но результат — нет.

На C #, если я изменю тип кодировки с UTF8 на Unicode, байтовый массив anidBytes изменится на это:

Unicode

Так что это идентично тому, что показывает отладчик C ++. Также меняется результат, но он все равно отличается от C ++. Вот новый результат C #:

C # Unicode результаты

Это правильный результат из C ++:

Правильный результат

2

Решение

Убедитесь, что вы разрезали байтовый массив ANID пополам, прежде чем использовать его в качестве секретного ключа для HMACSHA256. Алгоритму преобразования нужны только первые 44 байта, а не все 88. Не спрашивайте меня, почему, но AFAIK, это ошибка в коде C ++, который они используют при преобразовании ANID в ANID2, если вы посмотрите на пример кода на http://code.msdn.microsoft.com/wpapps/ANID-to-ANID2-Converter-cc428038 — Должно быть, они приняли Wchar за символ!

1

Другие решения

В C # для вашего HMACSHA256 объект, попробуйте установить свойство Key, а не инициализировать его в конструкторе.

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 говорит, что конструктор дополняет ключ до 64 байтов.

(Я не уверен на 100%, что делает установщик свойств, но это стоит попробовать).

1

public string Convert(string 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.ToBase64String(hashedBytes);
}
0
По вопросам рекламы [email protected]