写在前面:Rails 作为 Web 应用框架,其开发的项目常见部署在云服务端,提供 Web 服务。但如果项目作为独立的软件销售,该如何保护我们的利益呢?本文分享软件授权的一些经验。
本文适合商业软件开发者阅读,其中较少涉及 Ruby 和 Rails 具体技术,阅读时间10分钟。
一、软件卖出去之后
在过去的6年时间里,我的主要项目是一个网络设备的纳管平台,是基于浏览器的应用,这其中包括网络配置管理,WAF策略下发,集群架构部署等等。它不同于传统互联网 Web 服务,除了有 SaaS 版本外,还有独立的商业版。
商业版是靠卖授权来获得收益的,但是软件经常部署在客户外网隔离的环境中,我们无法实时监控软件的使用情况,这种情况下,该如何对软件进行授权呢?
首先,我们说授权过程中的三个风险。
软件激活秘钥(key)无限使用的风险
我们可能都用过激活成功教程的软件,比如windows,拿到镜像后,在网上搜激活码,没有激活码完全无法使用,但是搜到激活码多数也无法使用,要反复寻找尝试,找到个可用的要保存好留着下次激活再用。
还有一种是软件激活码生成器,自动生成可激活的 key。
授权 license 无限激活软件的风险
软件授权时,是对授权对象进行专属的激活,如果设计不当,得到的 license 就可以无限激活软件。如果软件试用版有一个月的试用期,则可以每月都激活它。
激活后的镜像拷贝滥用风险
成功激活软件后,导出的镜像分发给其他人导入到其他虚机使用,也可以突破软件的使用期限和授权范围。
二、key 的设计
讲完了风险,讲讲解决方案。
首先说key,如果我们只靠一个 key 来激活软件,像大多数软件那样,key要做到一点。
key 防伪造
key通过算法上的设计来防止伪造,这个设计的权力完全在设计者的大脑中。这也是软件开发者最自豪的,或者最自嗨的东西,叫做“创造力”。
好了,说说我的设计方案。因为参照了F5 的激活方式,所以我的 key 是 XXXXX-XXXXX-XXXXX-XXXXX 的格式,我叫它五四三格式。
也可以用 XXXXX-XXXXX-XXXXX 的格式,它是给测试版使用。
算法设计
接下来就是算法了。
算法设计的思路是,随机字符+校验字符。
随机位置和校验位置,随机字符和校验字符,完全取决于设计者的喜好。毕竟,清奇的脑洞自带一层加密,增加激活成功教程难度。
如上图,前三位是随机位,最后为校验位。
接下来是随机位字符产生。
虽说随机位的字符应该是随机产生,但是要留有校验符,这里为了省事,只留了一位,简单的说,XXXXX 五个字符,某一个是校验字符。又为了省事,这个校验符来自一个特定数组。
这样做的好处是,一是增加激活成功教程难度,二是随着软件升级,也可升级key的校验算法,V1、V2… … 的版本key可以迭代使用。
如果不看代码,我也不记得当时如何设计,它没有规律,直接上代码:
"#{rd(2)}#{rr(D1)}#{rd(2)}-#{rd(1)}#{rr(D2)}#{rd(2)}#{key_tra}-#{rr(D3)}#{rd(4)}"
rd(2) 方法产生2个随机字符,rr(D1)是在D1字典里取1个随机字符。
为了预留扩展功能,我在原本随机的字符里留了一个 key_extra 的字符作为标识。它可以启用某个模块,或者约定软件使用期限。
这样,随机位字符生成了。
校验位的字符很简单,SHA256取其摘要即可。这里有个掩人耳目的方式,我从摘要字串里取第2到第6位字符作为校验,
所以,key 的设计,是算法设计,是创作者的灵感。
三、dossier 和 license
key激活软件虽然方便,但是无法防止软件滥用,尤其是外网隔离的情况。所以,激活过程需要携带更多信息。
这里我参考了 F5 的授权激活方式。把携带授权对象的必要的信–它叫 dossier–传递出来后,在我们的授权平台–它叫主控端–生成 license,传递回软件后,激活授权对象。
dossier 换取 license
dossier 设计
所有从授权对象内拿到的消息,经过加密后,得到的文本就是 dossier。
这里的重点是,数据要体现授权对象唯一性,通常由多组单元数据组成,比如CPU型号,核数,内存大小,宿主机唯一码等等,它们可以由工具获得,要能充分体现授权对象的唯一性。例如 dmidecode 工具可以获得系统 uuid。
这里我不建议用 docker 方式部署,虽然方便,但是很难拿到宿主机的唯一信息,需要采用其它方式。
建议软件直接部署在宿主机上,或者直接提供安装镜像。因为大多数是外网隔离,所以我们的软件要具备离线安装。比如 Rails 项目, 就要把 gem 全部 bundle package –local 到 vender 目录里。
通过 dossier 里的参数,可以计算出一个重要属性:序列号,Serial Number(简写 SN),它通过算法得出,代表具体授权对象。其实我们的授权流程,就是对 SN 的授权和持续校验。
dossier 要做到保密,且不可篡改。在传递的时候,要用加密文本给我们。
license 设计
dossier 拿到后,在主控端解密后,再生成 license。既然 dossier 包含了授权对象的信息,我们可以把它保存下来,连同key一同保存,可以看到谁用哪个key做了激活。当然,你也可以完全做到“无状态授权”,只要 key 和 dossier 验证通过即可。
dossier 的验证可以自行设计了。
当验证成功,就是生成 license 了。这里可以包含基本的激活信息,比如 SN,授权时间,许可的软件参数,激活模块等等,建议增加附加信息字段,方便后续扩展。
这些文本生成后,再通过加密,传递给授权对象。
运行时校验
在完成授权后,需要在软件的运行时保持持续校验。比如每次重启时,授权对象的序列号是否有变动,是否和授权时的序列号相同,这是运行时校验的关键。
我们需要防止授权后篡改试用版和正式版标记,篡改授权时长,篡改授权模块等等。比如,拿一个低配的license激活试用后,通过更改关键数据,实现启用高级模块,延长试用期限等。
接下来的话题很关键,传递的密文如何加密和解密。
四、加密和解密
对于异步、异地的加解密的过程,我们需要在授权对象和主控端,分别完成加密和解密的动作。这时需要选择合适的加密算法。
对称加密
授权对象和主控端使用相同的 key,Rails 本身有很好的实现方案,实现方案简单。
同样缺点也明显,不仅仅是 key 授权两端都相同,有严重的泄露风险,甚至有激活成功教程整个授权机制的问题。而且 key 无法做到全部升级,我们不能给每个客户升级 key,每个客户使用相同的 key 也不安全。当我们升级算法时也存在升级动作过大的风险。
所以,建议使用非对称的方式。
非对称加密
公钥加密,私钥解密,我们可以效仿 HTTPS 的流程,进行公钥交换,这样实现了一器一密的方式。
或者,我们可以把每一次分发的商业版软件的私钥保存在自己主控端。
五、SDK设计
授权对象内部的的授权流程,可以抽象成SDK,在自己开发的软件系统里复用。其核心是四个方法:key 校验,生成 dossier,license 校验,运行时校验。
六、流程图
下图来自实际研发过程,核心要点是如何把概念改成代码。其中环节可自行设计,关键是要能经得起真实场景的验证。
七、代码加密
最后一个补充话题,如何保护我们的代码?
因为是用 ruby 语言完成的设计,Rails 应用的核心校验被抽象成一个 lib,至少我们要保护好这个lib的源码。
这里我用的 rubyencoder 这个商业工具,小贵,且每次 ruby 升级要购买新的版本,加密后代码是这样,通过自带的 rgloader 加载。用了6年了,还算稳定。
写在最后
这篇文章以设计思路的阐述为主,在实际开发中,2018年年底用ruby的方案实现到企业版中,后来用 java 按照原思路重构。
这篇文章算是篇备注,如果再不写下来,细节可能真的要忘光光了。
关于作者
李伟,网名里克,Ruby程序员,白帽子ing。
推荐阅读
-
Rails 应用安全参考
-
【Ruby on Rails】加密和解密
今天的文章软件分发平台是什么意思_手机端java开发工具[通俗易懂]分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:http://bianchenghao.cn/89250.html