【发布时间】:2015-06-29 09:33:35
【问题描述】:
Windows Phone 7 有一个名为 ANID 的匿名用户 ID 属性。 Windows Phone 8 已将其替换为 ANID2。不同之处在于 ANID2 取决于应用的发布者 ID。
可以在 MSDN 节目中将 ANID 转换为 ANID2 as the following code sample。您只需要原始 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++ 的正确结果:
【问题讨论】:
-
第一件事:您检查过
anidBytes和publisherGuid.ToByteArray()在二进制级别上是否与您在C++ 中使用的值相同? -
我添加了一些截图,似乎表明它们是相同的。
-
看起来该值在 C++ 版本中以 UTF-16 编码(因此每个字符有两个字节)。在 C# 中使用
System.Text.Encoding.Unicode而不是System.Text.Encoding.UTF8 -
感谢您的建议。不幸的是,结果仍然不同。我已经更新了帖子以反映这一点。
-
我还检查了所有的编码选项。 ASCII 和 UTF8 给出相同的结果,其他则不同。仍然没有一个匹配 C++ 输出。
标签: c# c++ windows-phone-8 cng