Windows Phone 7 有一个名为 ANID 的匿名用户 ID 属性。Windows Phone 8 已将其替换为 ANID2。不同之处在于 ANID2 取决于应用的发布者 ID。
可以将 ANID 转换为 ANID2 ,如 MSDN 上的以下代码示例所示。您只需要原始 WP7 ANID 和发布者 ID (guid)。问题是该示例是用 C++ 编写的。我一直在尝试将其移植到 C# 但没有成功。
算法本身很简单:
var data = HMAC(ANID, publisherId) // Uses SHA-256
var result = ToBase64(data)
问题是我无法获得结果匹配。我通过创建两个应用程序(WP7 和 WP8),在相同的设备上运行它们,然后使用发布者 GUID 从 WP7 应用程序转换 ANID 来确保 C++ 正常工作。在 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(密码学 API:下一代)的东西。这是其中的一些代码:
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++ 在每个字符之后都有这些 '\0' 字符,我不确定这是否可以。我认为是,因为两种情况下的长度都报告为 44。
另一个字节数组比较是publisherGuid (C#) vs pPublisherId (C++)(publisher id as GUID)。我认为他们再次匹配。C#:
C++:
如果我在值被加密后查看输出,我可以看到不同之处:
在 C# 上,我从这段代码中得到输出:
var macObject = new HMACSHA256(anidBytes);
var hashed = macObject.ComputeHash(publisherBytes);
字节数组如下所示:
在 C++ 代码中,如果我检查 pUniqueId(BCryptFinishHash 的结果),我会看到:
在这两种情况下,长度似乎相同,但结果却不同。
在 C# 上,如果我将编码类型从 UTF8 更改为 Unicode,则 anidBytes 字节数组将更改为:
所以它与 C++ 调试器显示的相同。结果也发生了变化,但它仍然与 C++ 不同。这是新的 C# 结果:
这是 C++ 的正确结果: