【Ruby on Rails】软件分发与授权

写在前面: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。

推荐阅读

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值