落格输入法是如何在 iOS 上反账号共享盗版的

对于 iOS 开发者来说,面对 app 盗版,最大的问题不是技术破解,反而是越来越多的 Apple ID 共享盗版,有的人可能会说这样的盗版就相当于是“试用”了,喜欢的人自然会去入正……但实际上,由于一分钱共享账号盗版的存在,导致无数独立开发者最终走向了投简历。

总之,去年,Surge 的作者发布了这么一篇文章 Surge 2.0 是如何实现在 iOS 上反盗版的 他的理论是从 app 购买的 Receipt 中得到一个唯一的时间戳,在一定程度上可以作为唯一用户的凭证。具体论证过程这里不再详述,这里我沿用了他的思路,所以本文的基础,是这个 original_purchase_date_ms 。

对于免费+内购的销售模式,如果要反账号共享的盗版,那么你应该取对应内购的时间戳而不是应用购买的时间戳。

自从 iOS 7 开始,苹果改进了 app 购买的回执,可能有些开发者不知道,即使没有内购,你也可以通过 StoreKit 来获取一个购买回执,这个回执就是用户购买 app 的回执。

服务器问题

读完 Surge 作者的这篇文章,你可能会遗憾——很可能你的 app 是一个工具类,就像落格输入法,它不需要登录甚至不需要联网就可以工作,所以它自然也就没有一个属于自己的服务器,那么怎么实现数据的存储呢?

这时候我们就可以使用苹果为所有开发者提供的 Cloud Database,你的 app 是通过系统的 API 进行通讯的,你无需为复杂的网络通信烦恼。

判断共享账号

这个时候有人会提出,如果你是按照激活来判断的,那么我同一个账号,下载了你的app,我删除了,再下载,不就和多人共享的过程是一样的了吗?即使按照 Surge 的规则,多达 10 次,那依旧有很大误判的概率。——没错,因为苹果对用户的隐私保护的太好,对于开发者是根本无法获取用户的 Apple ID 的,对于购买回执,也没有任何用户信息。

——但实际上,虽然我们不能得到 Apple ID 的明文数据,但开发者确实可以得到用户 Apple ID 的 hash 值!通过 CloudKit ,我们可以得到用户的唯一身份证明,比如这样:

你就可以得到如下的结果:

这就是用户的 Apple ID 。

那么,拥有了唯一购买标志,拥有了当前用户标志,一切就变得明朗了,我们只需要把两者保存起来,然后进行比对就可以了!

比如用户第一次购买的时候,我们得到购买标志,把它存入数据库,后续下载,只要用户的 Apple ID 与数据库中记录的值不同,那么计数就 +1,这样,就可以得到完全准确的分享次数了。

实际上,你的 Cloud Database 中完全不需要单独创建第一个购买用户的 id 这个字段,因为你可以直接检查创建者这个系统字段。同时,你还可以创建一个数组,顺便保存一下本次购买的 app 都有哪些用户共享安装了。

误杀重置

目前来看,这个思路我还没想到什么漏洞,对于可能的误杀,那就是人工重置了,开发者可以直接编辑 Cloud Database 的数据的,如果某用户需要重置,那么我们需要在 app 中显示购买的唯一凭证字段(即那个时间戳),通过这个凭证在数据库中找到对应条目,即可重置共享计数,或者查看共享的人数等等。

没有登录 Apple ID 的用户?

当然,本文所有的判断逻辑都建立在用户登录并启用 iCloud Drive 的前提之下(如果用户不启用,那么和断网是没什么区别的。如果你 app 的功能不依赖 Cloud Database,那么愿意牺牲 iCloud Drive 的用户就可以继续使用盗版而不会被发现)。那么我们假设:

  1. 共享账号在购买时没有登录 iCloud,并且没有打开 app,那么就无法记录。——这一点没关系,因为总会有用户购买这个共享账号并安装和使用 app,这样就会建立本次购买的记录;
  2. 用户在购买了共享账号后下载了app,但最终没有登录 iCloud。——如此一来 app 就不能访问数据库,检查和记录也就不存在了,如果用户愿意为了使用盗版而放弃 iCloud,那没办法了——本方案无效,用户可以继续正常使用盗版;
  3. 用户安装了共享 app 后,继续典型使用,但在第一次打开 app 前禁用了 app 的联网权限。——这样一来 app 无法联网,那一切就都是空谈了,用户可以继续使用盗版——对于一些对网络功能有依赖的 app 来说,或许用户就无法这么做了。对于落格输入法来说,用户就无法使用【对数云】中共享的内容以及共享内容到对数云。

额外疑惑:分享账号的 Apple ID 不是一样的么?

对于不这样使用盗版 app 的用户来说,这可能是个谜。实际上,使用共享账号的用户,并不会使用共享账号来登录 iCloud,也更不会绑定自己的设备到这个账号——这是使用共享账号盗版的常识。

总之,iOS 是允许在不退出 iCloud 的情况下更换 App Store 的账号的,这样一来,用户只需要使用共享账号登录 App Store 即可下载 app,这也是本文成立的前提,即用户最终还是会使用自己的 Apple ID 来日常使用,毕竟谁也不想被陌生人启用自己 iPhone 上的 “Find my iPhone”。

双账号问题

有些用户和我一样,是中区、美区两个账号,那么如果是这样,就有可能出现类似上文中共享账号的行为,比如中区购买,实际上 iCloud 使用的是美区,这里我们假设几种情况:

  • 使用主账号购买——这是典型使用情况,一切正常;
  • 使用小号购买,即 iCloud 登录的是另一个 Apple ID,那么在用户第一次打开 app 时,app 在数据库中添加的记录,实际上是用户当前登录的 Apple ID。——一切正常;

综上,那么实际上对于正常的双账号用户来说,影响是不存在的。当然,这建立在用户不会换着账号登录 iCloud,如果用户这么做,那么在另一个账号登录的时候,用户删除了 app,又重新下载了 app,还打开了一次,那么这时候共享计数 +1,但由于具有容错数量(比如 10 次),那么我们可以认为这样是足够一个用户在整个 app 生命周期来重装或者重置手机,更换 iPhone 的。

特别地,如果有用户很 2,他就要不停的删除重装,还用了非常用 Apple ID 登录了 iCloud,或者说他是用非常用 Apple ID 购买并已经配置好 app 然后才换回常用 Apple ID,再不停的删除重装,那我们还有最后一条补救措施——人工重置。通过人工重置,可以看到本次购买究竟共享给了多少个不同的 Apple ID,如果都是同一个,那么显然,这是一个误判。

隐私考虑

这样记录唯一信息,可能有些朋友会为隐私问题而担忧,这里我们分析一下:

数据安全

数据使用苹果公司提供的数据库服务,通信是通过 iOS 自身,开发者无法干预整个通信过程,完全依赖苹果公司自身的业界标准安全加密。

唯一凭证之 Apple ID

开发者能够获取的 Apple ID 的 hash,是仅供 Cloud Database 使用的唯一哈希,此数据仅对 Cloud Database 有意义,即使泄露,也无需担心,对于数据库的安全性,参考上一条。

唯一凭证之时间戳

这个时间戳是你在购买 app 时的付款时间,这个时间精确到毫秒,它可以用来粗略分辨单次购买的唯一性,但不足以与具体的 Apple ID 进行关联,所以即使与上一条结合,也无法定位具体的“某用户”,仅仅能得知是“确定的一位用户”。

总结

落格输入法的所有网络数据都保存在 Cloud Databse,结合一年来我对 Cloud Database 的使用,我在 Surge 作者的基础上总结出了这么一套精确判断共享用户的策略,可能优点就是不需要额外的服务器就能实现,且精准无误;缺点则是需要用户登录并开启 iCloud Drive,否则则无法判断。

Published by R0uter

如非声明,本人所著文章均为原创手打,转载请注明本页面链接和我的名字。

Join the Conversation

11 Comments

电子邮件地址不会被公开。 必填项已用*标注

  1. 我有点没明白。我是用中国账号下载的落格,iCloud也是中区,当然由于众所周知的原因,有可能要搬家。 但是由于Appstore中区很多app下架,我现在用了日区账号,并且挂了Suica,支付很方便,汇率也更优惠。日常使用中 我的Appstore实际上是日区账号,那么,我会被检测出来吗?

  2. 活着就是一切,活着就是乐,活着也有苦,苦里却也有乐;就如一片树叶,我该生的时候,我生气勃勃地来,长我的绿,现我的形,到该落的时候了,我痛痛快快地去,让别的叶子又从我的落疤里新生。