7.13 LimaxKey
LimaxKey简称Lmk,支持证书方式的客户端登录。客户端登录过程使用约定方式签署的私钥证书包。证书内容中包含了签署者信息,可以非常容易地追溯用户来源,事实上Lmk提供了去中心化的第三方登录机制。
-
7.13.1 设计要点
1. 为了简化客户端实现,提供Lmk私钥证书包格式LmkBundle,LmkBundle当前只支持RSA。提供LmkBundle格式和PKCS12等常用格式的互相转换工具。
2. 提供Lmk签署服务的实现。支持大型第三方机构,允许ROOTCA签署特定第三方CA证书LmkCA,LmkCA只能为自己的用户签署LmkBundle。支持小微第三方机构,允许通用CA为任何第三方机构签署属于自己的用户的LmkBundle。
3. Switcher,Auany帮助客户端更新证书。客户端登录之后,如果Switcher,Auany检测到客户端使用Lmk方式登录,并且达到证书更新时限,Switcher,Auany后台请求相应的Lmk签署服务获得新的LmkBundle存储在Auany上,客户端下一次登录时,将LmkBundle推送到客户端保存。(当然,客户端也可以定期到自己的签署机构获取新的LmkBundle)。
4. 特定情况下,允许通过配置,忽略证书过期检测。
5. LmkBundle可以用来绑定登录凭证,这样的凭证使用证书更新时限决定有效期。凭证过期,将导致客户端使用Lmk方式重新绑定凭证,这时Auany帮助客户端更新LmkBundle,下一次使用凭证登录的时候,更新的LmkBundle被推送到客户端保存。
6. 纯HTML5方式暂不支持Lmk登录,原因在于各种浏览器,HTTPS客户端证书密码提示的方式不能兼容。保存自动推送私钥证书包也要受到不同操作系统的安装限制。
-
7.13.2 客户端开发(以java客户端为例)
-
相关类与接口
1. limax.endpoint.LmkBundle
LmkBundle LmkBundle.createInstance(Octets lmkdata, Octets passphrase);
创建LmkBundle,lmkdata为保存在客户端的第三方机构为用户签发的私钥证书包文件数据,passphrase为文件密码。
Octets LmkBundle.save(Octets passphrase);
允许客户端自己更改LmkBundle密码,返回新的文件数据。
2. limax.endpoint.LmkUpdater (C#中为委托,C++中为函数对象)
void LmkUpdater.update(Octets lmkdata, Runnable done) throws Exception;
实现该接口,保存Switcher推送回来的更新的LmkBundle数据。lmkdata存储完成后执行done。
3. limax.endpoint.LoginConfig
其中,4个版本的LoginConfig.lmkLogin方法使用LmkBundle创建登录对象。
LoginConfig.setLmkUpdater(LmkUpdater lmkUpdater);
安装LmkUpdater对象。
-
客户端实现样式代码
LoginConfig loginConfig = LoginConfig.lmkLogin(LmkBundle.createInstance( Octets.wrap(Files.readAllBytes(Paths.get("/work/xxx.lmk"))), Octets.wrap("123456".getBytes()))); loginConfig.setLmkUpdater((lmkdata, done) -> { Files.write(Paths.get("/work/xxx.lmk"), lmkdata.getBytes()); done.run(); });
-
注意事项
1. 如果使用Lmk方式创建的凭证,那么通过LoginConfig.credentialLogin创建登录对象之后,同样需要执行loginConfig.setLmkUpdater安装LmkUpdater对象。
2. 从安全角度看,LmkUpdater应该设计为LmkUpdater.update(LmkBundle lmkBundle),用户存储LmkBundle时自己设置一个密码。这种方式,需要使用LmkBundle.save重新设置密码,加密LmkBundle后再执行存储,用户通常难以接受。实际实现时,passphrase在登录过程中被上传到服务器,如果需要更新LmkBundle,即用该passphrase加密,推送回客户端。所以LmkBundle.save方法应该少用,避免冲突。
3. 服务器实现上保证了LmkBundle更新事务的完整性,整体完整性的保证必须有客户端的参与。具体实现上,如果登录过程中检测到Auany已经存储了更新的LmkBundle,Switcher返回给Endpoint的上线通告中就提供了这个LmkBundle,Endpoint收到上线通告立即触发LmkUpdater,lmkdata存储完成后执行done,通告Auany清除存储的LmkBundle。
4. 参见《PKIX支持》,Location一节,其中scheme增加了LMK类型,使用上与PKCS12类似,可以通过 java -jar limax.jar pkix copy <locationSRC> <locationDST>执行格式转换,非RSA的情况下执行失败,另外,为了节省空间,Lmk签署服务发行的LmkBundle中不包含根证书,向其它格式转换也会失败。
-
-
7.13.3 签署LmkBundle
-
设计原则
1. Limax框架提供了Lmk签署服务,支持签署与回收LmkBundle。
2. 有能力部署Lmk签署服务的大型三方机构,可以使用自己的LmkCA证书运行签署服务,为自己的用户发行LmkBundle。
3. 没有能力部署Lmk签署服务的小微三方机构,可以请求自己的客户端证书,访问通用CA证书上运行的签署服务,为自己的用户发行LmkBundle。
-
创建LmkCA
java -jar limax.jar pkix initlmkca <locationROOT> (<locationCA>|<keygen/.pub>) <subject> <domain> <yyyyMMdd> <yyyyMMdd> <OcspDomainOfRoot>
使用ROOTCA证书,签署一个三方机构的LmkCA,与签署通用CA证书(参见《PKIX支持》)的区别在于这里多了一个domain参数,该参数与Auany配置中平台名等价,允许和平台名重名,这意味着这个第三方机构,既支持通常的三方登录方式,也可以支持Lmk方式。
例如:
java -jar limax.jar pkix initlmkca "file:ca@/work/pkix/root" "file:lmkca@/work/pkix/ca/#rsa/2048" "dc=lmkca,dc=limax-project,dc=org" "lmkca.limax-project.org" "20170101" "20300101" "root.limax-project.org"
-
签署Lmk服务请求证书
注意,这里的dNSName,即是Auany中对应的平台名。
-