Windows Store 应用获得设备 ID 的几种方案

本文为个人博客备份文章,原文地址:

http://validvoid.net/solutions-get-device-id-for-uwp/

通过生成唯一的设备 ID 进行数据统计是应用开发中一个非常常见的需求,然而自从 WP 7.8 开始,WP 平台上就无法再获得一个唯一的,不变的,且不同应用间一致的设备 ID 了。本文总结了几种在 Windows Store 平台上用于统计设备 ID 的方案,开发时可以根据具体需求进行选用。

1. 广告 ID

广告 ID 主要用于通过分析用户安装了哪些应用并如何使用来优化广告推送的相关性和频率等行为,同时也用于检测广告欺诈以及其它一些安全问题。

public static string AdvertisingId { get; }

特点

  • 每用户、每设备唯一
  • 应用间一致

缺点

  • 广告 ID 并非持续可用,用户可以在系统设置的隐私选项或组策略中关闭广告 ID。
  • 广告 ID 并非永久唯一,以下情况会导致广告 ID 发生变化:
    • 用户关闭广告 ID 后重新开启广告 ID,广告 ID 会重新生成。
    • 用户重置或升级设备(手机、PC等)操作系统后,广告 ID 会重新生成。
  • 由于广告 ID 是每用户、每设备唯一的,故广告 ID 不会随着用户账户在不同设备间漫游。
  • 广告 ID 无法在儿童账户中开启。

使用方法

var advertisingId = Windows.System.UserProfile.AdvertisingManager.AdvertisingId;

 

广告 ID 关闭时,使用上述 API 获得广告 ID 的返回值为空。

MSDN 文档

AdvertisingManager.AdvertisingId | advertisingId property

2. EasClientDeviceInformation

EasClientDeviceInformation 类用于获取本地 ExchangeActiveSync 设备的信息。其中有一个 Guid 类型的 Id 属性,可以获得设备 Id。

public Guid Id { get; }

 

返回本地计算机的标识符。Id 属性表示 DeviceId(使用从 MachineID、用户 SID1 和包系列名称 (PFN)2 的 SHA256 哈希值截断的前 16 个字符 GUID,其中 MachineID 使用本地用户组的 SID)。GUID 的每个组件以网络字节顺序返回。

特点

  • 每用户、每设备、每应用唯一

缺点

  • 每应用唯一

由于构成 EAS 客户端设备信息 ID 的元素中包含包系列名称 (PFN),故 EAS 客户端设备信息 ID 是每应用间唯一的。假设你有多款应用均要通过设备唯一 ID 进行数据统计,那么同一台设备上的两个应用返回的将是两个不同的 ID。

使用方法

var easId = new Windows.Security.ExchangeActiveSyncProvisioning.EasClientDeviceInformation().Id;

 

MSDN 文档

EasClientDeviceInformation class

3. 应用特定硬件 ID (ASHWID)

应用特定硬件 ID(缩写为 ASHWID)通过表现设备硬件特征实现唯一设备的识别。ASHWID 适用于限制应用分发目标设备的数量,或者限制每设备使用唯一的授权。

特点

  • 每设备、每应用唯一
  • 用户间一致
  • 不会因以下操作而发生改变:
    • 操作系统重新安装
    • 推送按钮重置
    • 操作系统 SKU 升级
    • 应用的版本更新
    • 在同一设备上更改用户
  • 可验证真实性

缺点

  • 值会随着设备硬件的改变而改变

ASHWID 的构成

ASHWID 由当前设备的组成硬件以及当前应用包名称生成。

ASHWID 会根据以下九种可能的硬件组件进行生成,每个硬件组件都对应 ASHWID 返回的字节流的一部分:

  1. 处理器的 CPU ID
  2. 内存大小
  3. 磁盘设备的序列号
  4. 网络适配器(例如 NIC MAC 地址)
  5. 音频适配器
  6. 扩展坞
  7. Bluetooth 地址
  8. 移动宽带设备 ID
  9. BIOS

ASHWID 可能并不恰好包含 9 个组件 ID。可能的原因包括:

  • 目标硬件可能不是恰好具备 9 个独立组件。例如,桌面可能没有扩展坞。
  • 设备可能具备相同类型的多个组件。例如,可能有两个音频适配器。
  • 每个物理磁盘驱动器都对应一个组件 ID。具有 3 个物理磁盘驱动器的桌面系统会返回 3 个组件 ID。
  • 当平板电脑设备连接到扩展坞时,会返回其他网络 (Ethernet) 适配器和音频适配器(来自 HDMI 或模拟音频输出端口)的组件 ID。

ASHWID 的字节流标识了硬件组件的类型和值,参加下表:

字节流表示组件
1,0 处理器
2,0 内存
3,0 磁盘设备
4,0 网络适配器
5,0 音频适配器
6,0 扩展坞
7,0 移动宽带
8,0 Bluetooth
9,0 系统 BIOS

以上表格摘自 MSDN 文档。

出于隐私安全的考虑,ASHWID 生成时会考虑应用包名称,因而在同一台设备上的两个应用获取到的 ASHWID 是不同的。而只要设备硬件不发生改变,同一台设备上的同一个应用多次获得的 ASHWID 总是相同的。

ASHWID 示例

不同组件 ID 的枚举顺序没有必要连续。以下流显示少量 ASHWID 示例。注意,在流中,组件 ID 的数字及其顺序会不同。

7,0,124,215,3,0,206,143,8,0,128,55,5,0,12,222,5,0,128,255,6,0,1,0,4,0,20,22,4,0,48,155,1,0,250,155,2,0,162,217,9,0,92,101

Samsung Intel Core i5 平板电脑上发现的移动宽带。

7,0,124,215,3,0,206,143,8,0,128,55,5,0,126,129,5,0,12,222,5,0,128,255,6,0,1,0,4,0,20,22,4,0,48,155,4,0,178,193,1,0,250,155,2,0,162,217,9,0,92,101

当靠接时同一设备上有三个不同音频适配器和当靠接时同一设备上有三个不同网络适配器。

3,0,188,97,3,0,76,128,3,0,250,138,5,0,220,130,6,0,1,0,4,0,20,164,1,0,204,49,2,0,226,37,9,0,22,72

桌面上发现三个不同磁盘。

3,0,24,211,5,0,182,46,5,0,54,49,6,0,1,0,4,0,203,9,1,0,148,99,2,0,162,255,9,0,140,234

Nvidia Tegra 3 设备。你可能会注意到流“6,0,1,0”与扩展坞对应,不论设备或外形规格如何。

以上示例摘自 MSDN 文档。

使用方法

要获得 ASHWID,可以使用 HardwareIdentification.GetPackageSpecificToken 方法。

该方法接受一个参数 IBuffer noncenonce 为仅使用一次的数字。通常此数实现为随机数,该数足够大,可降低数字重复使用的可能性。nonce 用在身份验证协议中,可防止重播攻击。

该方法返回一个 HardwareToken 类型。HardwareToken 类型表示包含了一个足够唯一的基于硬件的标识的标记。

HardwareToken 类型包含以下三个属性(均为 IBuffer ):

  • Certificate:获得用以签名硬件特定 Id 的证书以验证 Id 真实性。
  • Id:获得硬件特定 Id。
  • Signature:获得硬件特定 Id 的签名以验证 Id 真实性。
HardwareToken packageSpecificToken;

packageSpecificToken =  Windows.System.Profile.HardwareIdentification.GetPackageSpecificToken(nonce);

IBuffer hardwareId  = packageSpecificToken.Id;
IBuffer signature = packageSpecificToken.Signature;
IBuffer certificate = packageSpecificToken.Certificate;

var dataReader = Windows.Storage.Streams.DataReader.FromBuffer(hardwareId);  

byte[] bytes = new byte[hardwareId.Length];  
dataReader.ReadBytes(bytes);  

string id = BitConverter.ToString(bytes);

 

验证 ASHWID 有效性

若要使用 ASHWID 实现正版授权验证、限制应用分发等需求,可以通过使用可选的 nonce、签名以及证书结合应用的云端进行验证。

在调用 GetPackageSpecificToken 方法时,可以传入 IBuffer 类型的 nonce 参数。通过每次提供不同的 nonce,云端可以据此来验证所返回的 ASHWID 实际上来自 Windows 且未由用户重播。

除非云端不关心重播攻击或 ASHWID 的处理仅在客户端完成,则不推荐为 GetPackageSpecificToken 方法传递空的 nonce。

由于 ASHWID 会随着设备硬件的改变而改变,故云端在验证 ASHWID 时,需要响应地计算 ASHWID 的变化量,在容许的范围内判断许可授权的有效性。

有关在云端验证 ASHWID 的更多说明,可以参阅 MSDN 文档 《有关使用应用特定硬件 ID (ASHWID) 实现每设备应用逻辑的指南》


  1. SID 全称 Security Identifier,即“安全标识符”。 SID 由 Windows 域控制器等权威方发布,用于标识用户、用户组和计算机账户。每创建一个账户,系统都会为该账户分配一个唯一的 SID。即便删除某账户,再以完全相同的名称创建一个新账户,新账户的 SID 也是不同于旧有账户的。用户登录时,SID 作为用户访问凭据的一部分由系统使用来判断当前用户是否有执行某项操作的权限。有关 SID 的更多信息,可以参阅文档 Security Identifiers。 

  2. 即 Package family name (PFN),指与经过哈希的发布者名称连结的程序包名称。 

posted @ 2015-11-18 11:56  void²  阅读(2209)  评论(0编辑  收藏  举报