Java 自签名证书验证未在Android中引发SignatureException

Java 自签名证书验证未在Android中引发SignatureException,java,android,exception,ssl,x509certificate,Java,Android,Exception,Ssl,X509certificate,在下面一段Android应用程序代码中,服务器向连接的Android客户端提供一个自签名证书。也就是说,我已使用自己的CA对服务器的证书进行了签名。该证书将使用CA的公钥进行验证,该公钥是从/raw中放置的名为trust\u store\u CA的文件中获取的。问题是,如果我使用不同的证书(使用不同的CA签名,即),验证步骤不会抛出相应的SignatureException。我已经在NetBeans中测试了代码,它确实抛出了上述异常。但是,在AndroidStudio中,它不。问题可能是什么 K

在下面一段Android应用程序代码中,服务器向连接的Android客户端提供一个自签名证书。也就是说,我已使用自己的CA对服务器的证书进行了签名。该证书将使用CA的公钥进行验证,该公钥是从/raw中放置的名为trust\u store\u CA的文件中获取的。问题是,如果我使用不同的证书(使用不同的CA签名,即),验证步骤不会抛出相应的SignatureException。我已经在NetBeans中测试了代码,它确实抛出了上述异常。但是,在AndroidStudio中,它不。问题可能是什么

KeyStore ts = KeyStore.getInstance("BKS");
InputStream trustin = v.getResources().openRawResource(R.raw.trust_store_ca);
ts.load(trustin, "MyKey".toCharArray());
// Create own trustmanager with self-signed cert.
final TrustManagerFactory tmf = TrustManagerFactory.
    getInstance(KeyManagerFactory.getDefaultAlgorithm());
//tmf.init((KeyStore) null);
tmf.init(ts);
trustManagers = tmf.getTrustManagers();

CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream cA_certificate = v.getResources().openRawResource(R.raw.ca_certif);
final X509Certificate caCertificate = (X509Certificate)cf
    .generateCertificate(cA_certificate);
// Check server certificate is valid
final X509TrustManager origTrustmanager = (X509TrustManager)trustManagers[0];

wrappedTrustManagers = new TrustManager[]{
                                    new X509TrustManager() {
    @Override
    public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                                            return origTrustmanager.getAcceptedIssuers();
                                        }
    @Override
    public void checkClientTrusted(X509Certificate[] certs, String authType) {//Not used}

    @Override
    public void checkServerTrusted(X509Certificate[] certs, String authType) 
throws CertificateException{
    if (certs == null || certs.length == 0) {
        throw new IllegalArgumentException(
"checkServerTrusted: null or zero-length certificate chain");
    }
    if (authType == null || authType.length() == 0) {
        throw new IllegalArgumentException(
"checkServerTrusted: null or zero-length authentication type");
    }

// This does not work in Android, at least from me in JB...
//
// try { 
//      certs[0].verify(caCertificate.getPublicKey(), "BC");
//      Log.i(TAG,"Pubkey for caCertificate: "+ caCertificate.getPublicKey());
//      } catch (CertificateException | NoSuchAlgorithmException | 
//           NoSuchProviderException | InvalidKeyException | SignatureException e)
//            {Log.i(TAG,"Certificate verification exception" + e);}
//

// Do signature verification by decrypting it and comparing to expected
// value (01FFFFFFFFFFFFFFF.....FFFFFF003021300906052B0E03021A05 000414... etc)

byte[] signature = certs[0].getSignature();   // signature in server's certif.
BigInteger exp = new BigInteger("010001",16); // 65537 as usual
BigInteger decrypt_sign = new BigInteger(1, signature).modPow(exp, ca_pubkey.getModulus());
System.out.println("Signature after decryption: " +decrypt_sign);
编辑:我正在覆盖验证过程,因为它没有检测到假证书。请参阅我的代码版本,现在只需根据预期检查解密值

见:

非常好的解释


同时,感谢所有帮助过我的人。:)

这可能与以下事实有关:
证书[0]可能会引发一系列异常(捕获而不是重新抛出)。请验证

谢谢。正如我前面提到的,代码在Android环境之外运行正常(在我的例子中是NetBeans),实际上捕获SignatureException并打印到控制台。你还认为我应该修改那部分代码吗?你有什么建议?提前感谢。Android上有很多加密库是不同的——请记住,这是一个不同于纯Java的环境。因此,当您使用Android时,很可能会在不同的位置抛出不同的异常。您应该适当地处理所有异常,不要“吃掉”它们。@user46718您在android上的日志中是否有“证书验证异常”一行?@vlp不,没有,这就是问题所在。不管怎么说,我不得不继续这样做,所以我最终决定手动计算它(请参见编辑)。