本文讨论的是在无合法CA证书,但又必须使用HTTPS API,Google应用审核通不过的处理方式。
从HTTP请求转成HTTPS,我们需要自定义X509TrustManager,因为使用无效CA证书,所以也不能实现安全校验逻辑,否则无法调用到正常的流程,代码如下:
TrustManager tm = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
//do nothing,接受任意客户端证书
}
public void checkServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
//do nothing,接受任意服务端证书
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
以这样的代码打包出来的APK提交到Google Play Store后就是看运气,有可能没查到就让你通过了,有可能查到,就是拒绝,以下就是被拒情况下的处理方法:
一、使用伪认证
假装认证,抛出异常:
public class TrustAllManager implements X509TrustManager {
@Override
public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
if (arg0 == null){
throw new IllegalArgumentException("X509Certificate array is null");
}
if (!(arg0.length > 0)){
throw new IllegalArgumentException("X509Certificate is empty");
}
if (!(null != arg1 && arg1.equalsIgnoreCase("RSA"))) {
throw new CertificateException("AuthType is not RSA");
}
}
二、破解认证
- 获取CA证书的KEY数据,在checkServerTrusted()方法中,把chain数组打出,保存成全局变量。
- 实现安全校验逻辑:
public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
if (arg0 == null){
throw new IllegalArgumentException("X509Certificate array is null");
}
if (!(arg0.length > 0)){
throw new IllegalArgumentException("X509Certificate is empty");
}
if (!(null != arg1 && arg1.equalsIgnoreCase("RSA"))) {
throw new CertificateException("AuthType is not RSA");
}
RSAPublicKey keys = (RSAPublicKey) arg0[0].getPublicKey();
String encode = new BigInteger(1,keys.getEncoded()).toString(16);
boolean expected = PUBLIC_KEY.equalsIgnoreCase(encode);
if (!expected){
throw new CertificateException("Certificate not valid or trusted.");
}
}
重新打包提交,基本上可以PASS了,且保证不影响原来的逻辑,当然要是对方的CA证书更换或修改,那又得重新读取Key数据。
对于有效CA,却通不过的问题,不在此讨论范围内。