App中敏感信息处理
在App开发中,特别是金融行业的App开发过程中,会涉及到手机号,身份证号,银行卡号等敏感信息,这些信息的展示和传输不能够直接使用明文的,否则极容易进行信息泄露。下面介绍下我们的处理过程。
# 敏感信息
目前在App中有以下敏感信息:
- 手机号
- 密码
- 身份证
- 银行卡号
- UserId
- UserName
# 加密算法现状
App中主要使用AES、RSA算法。其中AES的秘钥App中使用属性字符串(其实并不安全,很容易被反编译拿到),RSA有服务端公钥(简称SPub)和客户端私钥(简称CPriv),实际是服务端维护的两对RSA算法的公私钥,将其中一对的公钥和另一对的私钥通过AES加密方法得到密文给客户端使用(即前面提到的SPub和CPriv),其中公钥用来客户端RSA算法加密,私钥用来网络请求参数签名。SPub和CPriv使用AES加密,其中AES秘钥使用一个源key通过算法计算而来(源key->Base64->转大写->字符串翻转->MD5->截取前16位),而源Key在App中使用属性字符串存储。
由此可见,AES算法的密文在本地存储和网络传输中均不安全,而SPub和CPriv的AES加密在对应的私钥和公钥未泄露时又显得没必要。
# 敏感信息本地存储
有些未经加密,直接存储在NSUserDefault中,有些是经过AES加密存储在NSUserDefault中
# 敏感信息网络传输
- 手机号 (AES加密)
- 密码 (RSA加密)
- 身份证 (AES)
- 银行卡号 (AES)
- UserId (未加密)
- UserName (AES)
# 解决方案
# 本地信息存储
使用DeviceId加盐,使用算法生成AES秘钥,将信息加密后做本地存储,一定程度上提高本地信息存储的安全,iOS将存储到NSUserDefault改为存储到KeyChain, Android还是存储到文件中。
注意:涉及到服务端返回的AES加密数据存储,客户端需要先解密,然后再用本地AES秘钥加密进行存储
# 网络传输
HTTPS + Certificate Pinning (已经实现)
Perfect Forward Secrecy,主要涉及到ECDH算法进行秘钥交换
- 服务端存储一份根据ECDH算法算出的公私钥(可定时更新)
- 客户端根据ECDH生成一对临时的公私钥(时机可以选择每次启动或者每次发送敏感信息)
- 客户端App启动时(或者服务端解密出现错误时,表示服务端公私钥进行了更改)从服务端获取公钥,通过公钥计算出共享的preMaster Key,再用哈系函数处理preMaster key计算出AES的加密/解密密钥
- 在传输敏感数据时,使用AES算法进行加密,将加密结果连同客户端公钥传递到服务端
- 服务端根据客户端公钥计算出共享的preMaster Key,再用哈系函数处理preMaster key计算出AES的加密/解密密钥,然后进行AES解密
下发过程敏感信息进行脱敏处理