В Windows Phone 7 было свойство анонимного идентификатора пользователя, называемое ANID. Windows Phone 8 заменил его на ANID2. Разница в том, что ANID2 зависит от идентификатора издателя приложения.
Можно преобразовать ANID в ANID2 в следующем примере кода на MSDN показывает. Все, что вам нужно, это исходный WP7 ANID и идентификатор издателя (guid). Проблема в том, что пример на C++. Я пытался портировать его на С#, но безуспешно.
Сам алгоритм довольно прост:
var data = HMAC(ANID, publisherId) // Uses SHA-256
var result = ToBase64(data)
Проблема в том, что я не могу добиться совпадения результатов. Я убедился, что C++ работает правильно, создав два приложения (WP7 и WP8), запустив их на одних и тех же устройствах, а затем преобразовав ANID из приложения WP7 с помощью GUID издателя. На C++ преобразованный ANID2 и ANID2 с устройства совпадают. На C# конвертированный ANID2 — это что-то другое.
Код С# прост:
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++ имеет эти символы '\0' после каждого, и я не уверен, что это нормально. Я думаю, что да, так как длина в обоих случаях указана как 44.
Другое сравнение массива байтов — это publisherGuid (C#) и pPublisherId (C++) (идентификатор издателя в виде GUID). Я думаю, что они снова совпадают. С#:
C++:
Если я затем посмотрю на вывод после того, как значение было зашифровано, я увижу разницу:
На С# я получаю вывод из этого кода:
var macObject = new HMACSHA256(anidBytes);
var hashed = macObject.ComputeHash(publisherBytes);
И массив байтов выглядит так:
В коде C++, если я проверю pUniqueId (результат BCryptFinishHash), я увижу это:
Длина кажется одинаковой в обоих этих случаях, но результат - нет.
В C#, если я изменю тип кодировки с UTF8 на Unicode, массив байтов anidBytes изменится на это:
Так что это идентично тому, что показывает отладчик C++. Также меняется результат, но он все еще отличается от C++. Вот новый результат C#:
Это правильный результат от С++:
anidBytes
иpublisherGuid.ToByteArray()
на двоичном уровне идентичны значениям, которые вы используете в C++? - person Kevin Gosse   schedule 01.08.2013System.Text.Encoding.Unicode
в C# вместоSystem.Text.Encoding.UTF8
- person Kevin Gosse   schedule 01.08.2013