alwaystest / Blog

24 stars 2 forks source link

Android CI 与 KeyStore #81

Open alwaystest opened 6 years ago

alwaystest commented 6 years ago

Android CI 与 KeyStore

标签(空格分隔): Android


之前做Android项目的CI的时候遇到过如何管理签名文件的问题,但是当时没有好的解决思路,直到最近看到这个项目的配置

https://github.com/YoKeyword/Fragmentation

签名Key的重要性

非对称加密是目前广泛应用的一种加密和签名认证方式。具体的原理这里就不多讲了。我们使用私钥对APK进行签名,在应用升级的时候,系统要求升级前后的应用包名一致,签名一致。也就是说,要求应用签名的时候,要使用同一个私钥。私钥泄漏,就可能被别人拿来伪造应用。从安全的角度来讲,应用的签名文件应该被严格管理,因为一旦泄漏,就有可能被拿到签名Key的人伪造应用,造成损害。

一般来讲,为了安全,会把应用的源码和应用的KeyStore分开保存,划分权限管理。限制正式版APK只能由有权限的Dev签名生成,开发版的应用统一使用相同的开发版KeyStore,这样,各个Dev产出的安装包可以互相覆盖升级,不会有签名冲突的问题。

但是这样的效率也太低了,要Build正式版的安装包,只能找有权限的Dev。

使用CI来解决这个问题,KeyStore存储在服务器上,对外只暴露一个Build触发器,Build流程由CI控制,而Build流程的控制现在都会与源码放在一起做统一的版本管理。这样,源码,签名Key互相隔离,Build也不会受限。这个解决方案需要有一台可以保证安全的服务器,否则KeyStore暴露在服务器上,如果服务器被黑,KeyStore依然会被泄漏。使用公共CI服务的开发者肯定不能接受这个解法。

使用公共CI服务的情况下,就可以参照 https://github.com/YoKeyword/Fragmentation 的解法,把KeyStore加密处理,和源码放在一起。在Build流程中增加一个解密步骤,解密使用的密码就不能和源码一起存放了。这部份可以使用环境变量,在CI服务上单独把解密KeyStore的密码使用环境变量存储,这样就保证了安全性。同时,下面几个签名使用的变量也使用环境变量做了隔离。

        keyAlias KEYSTORE_ALIAS
        storePassword KEYSTORE_PASSWORD
        keyPassword KEY_PASSWORD

其实我感觉一个密码和多个密码使用环境变量保存好像并没有多大差别,只要是同一种方式,泄漏了一个密码,其他密码也可以被相同的方法拿到。所以是不是把签名使用的变量使用环境变量隔离,KeyStore文件就可以不用加密了呢?

最后,个人感觉这个解法还是不能保证万无一失,毕竟在Build的过程中还是生成了解密后的KeyStore文件,根据机械硬盘的特性,数据被标记删除后,在被覆写前还是可以还原回来的,甚至被覆写后还是有可能还原回来的。CI过程中的容器就一定能保证不会被Hack吗?

没有穿不破的盾。毕竟非对称加密也只是目前无法快速破解而已,UUID的解法也不能保证完全无冲突。在更好的方案出来之前,已知的最好方案就是最好的方案,