Android 数据加密及安全网络通信杂谈(二)

(续前文)
补充前文:凡是代码中使用到 KeyChain 包 的 API,勿忘记在 AndroidManifest.xml 中加入 "android.permission.USE_CREDENTIALS" 权限。


有时候,App 可能需要查验某个证书(譬如从签名邮件或者数字信封、时间戳里获取的“签名者”)是否“可信”,可从系统凭证库的“CA”库中取出所有的“可信颁发者”证书(包括系统预装的以及用户自行安装的)对其进行检验:


//获取系统凭证库里的 CA 证书,查验证书的可信性
X509Certificate cert = ....; //待查验的证书
X509Certificate CAcert;
KeyStore mCAStore = KeyStore.getInstance("AndroidCAStore");
mCAStore.load(null, null);
Enumeration<String> als = mCAStore.aliases();
while (als.hasMoreElements()) {
    CAcert = (X509Certificate) mCAStore.getCertificate(als.nextElement());
    try {
        cert.verify(CAcert.getPublicKey());
        Log.i("CA found: ", CAcert.toString());
        break;
    } catch(Exception e) {
        CAcert = null;
    }
}
if (CAcert == null) Log.i("CA not found.", "He he");


前文提到安装证书到系统凭证库时,系统会自动根据所安装的证书是否 CA 证书来决定安装在哪里,如果待安装的用户证书不是随着密钥对一起安装的话,实际上是没有意义的,所以在安装之前,有必要判断一下待安装的是否 CA 证书:
//判断某证书是否一个 CA 证书
public boolean isCA(X509Certificate cert) {
    if (cert.getBasicConstraints()) < 0 return false;
    boolean[] kusg = cert.getKeyUsage();
    return kusg[5] && kusg[6];
}
是不是超简单?


曾经有人问过本人,系统凭证库的 API 只有安装和读取功能,有没有办法列举、删除里面的证书、私钥?答案是有的,这涉及到 Android 一个未公开的类:android.security.KeyStore(注意,这不是 JCE 的那个KeyStore)。既然是未公开的类,编译的时候还真有点小麻烦,另外不同版本的 Android 里这个类的内容也有不同,有一位大牛已经考虑到了这点,专门做了个项目方便我们编程时引用:
https://github.com/nelenkov/android-keystore 去下载下来,里面有测试代码,这里简单介绍一下你可能感兴趣的:
public byte[] get(String name),读内容,如果要读的是私钥,有些版本可能读到的数据不是你所想象的;
public boolean put(String name, byte[] value),写内容;
public boolean delete(String name),删除内容;
public String[] saw(String prefix),列出以 prefix 为开头的所有 name,在 Android 6.0 中,该方法已经更改为
public String[] list(String prefix) 了(Google 可恶吧?);
那么这个 prefix 怎么取值呢?"CACERT_"、"USRCERT_"、"USRPKEY_"、"VPN_"、"WIFI_",望文生义就不用解释了吧,如果想列出所有 name,用 "" 即可。
请花点时间读一下这篇文章,会少走些弯路:http://doridori.github.io/android-security-the%20forgetful-keystore/


3、AndroidKeyStore,从 4.2 开始,增加了这个 Service Provider,可以像 JCE 其他类型的 KeyStore 一样对其操作,当然还是有些许差别的:
KeyStore ks = KeyStore.getInstance("AndroidKeyStore");
ks.load(null, null);
KeyStore.Entry entry = ks.getEntry(alias, null);
从以上代码可以看出,所有关于密码的参数都是 null,因为 AndroidKeyStore 是由锁屏功能来进行保护的,所以不需要 password 了,请参阅 SDK 文档 docs/training/articles/keystore.html
从 4.3 开始,AndroidKeyStore 新增了一些方法用于生成“自签名证书”,到了 6.0,又新增了 android.security.keystore 这个包(注意,不是 android.security.KeyStore 这个一直未公开的类),本人不赞成用这方法来生成证书,理由后文再论。


小结:本文假设你在 Java、JCE、JSSE、PKI 方面有较
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值