Android的SSL没有同行证书(Android SSL No peer certificate)

2019-08-31 16:58发布

我有一个例外:没有对方的证书

当我问谷歌,然后我得到的解决方案,在那里我相信所有证书。 但这个问题的答案是,它是不安全的。

因此,我调用的类:

HostnameVerifier hostnameVerifier = org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;
           HttpClient client = new DefaultHttpClient();

           SchemeRegistry registry = new SchemeRegistry();
           SSLSocketFactory socketFactory = SSLSocketFactory.getSocketFactory();
           socketFactory.setHostnameVerifier((X509HostnameVerifier) hostnameVerifier);
           registry.register(new Scheme("https", socketFactory, 443));
           SingleClientConnManager mgr = new SingleClientConnManager(client.getParams(), registry);
           DefaultHttpClient httpClient = new DefaultHttpClient(mgr, client.getParams());

           HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);
           Log.v("URL:", Url[0]);
           HttpPost post = new HttpPost(Url[0]);  
           post.addHeader("Username", Url[1]);
           post.addHeader("Passwort", Url[2]);
           HttpResponse getResponse = httpClient.execute(post); //Wirft Exception
           HttpEntity responseEntity = getResponse.getEntity();
           UserID = Integer.parseInt(responseEntity.getContent().toString());

这是我的课:

class MyHttpClient extends DefaultHttpClient {

final Context context;

public MyHttpClient(Context context) {
    this.context = context;
}

@Override
protected ClientConnectionManager createClientConnectionManager() {
    SchemeRegistry registry = new SchemeRegistry();
    registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
    // Register for port 443 our SSLSocketFactory with our keystore
    // to the ConnectionManager
    registry.register(new Scheme("https", (SocketFactory) newSslSocketFactory(), 443));
    return new SingleClientConnManager(getParams(), registry);
}

private SSLSocketFactory newSslSocketFactory() {
    try {
        // Get an instance of the Bouncy Castle KeyStore format
        KeyStore trusted = KeyStore.getInstance("BKS");
        // Get the raw resource, which contains the keystore with
        // your trusted certificates (root and any intermediate certs)
        InputStream in = context.getResources().openRawResource(R.raw.mykey);
        try {
            // Initialize the keystore with the provided trusted certificates
            // Also provide the password of the keystore
            trusted.load(in, "PASSWORT".toCharArray());
        } finally {
            in.close();
        }
        // Pass the keystore to the SSLSocketFactory. The factory is responsible
        // for the verification of the server certificate.
        SSLSocketFactory sf = new SSLSocketFactory(trusted);
        // Hostname verification from certificate
        // [url=http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d4e506]Chapter2.Connection management[/url]
        sf.setHostnameVerifier(SSLSocketFactory.STRICT_HOSTNAME_VERIFIER);
        return sf;
    } catch (Exception e) {
        throw new AssertionError(e);
    }
}

}

Answer 1:

我已经发现了SSLPeerUnverifiedException的另一个可能的原因:没有对等证书

如果你的模拟器与那就是当证书已经创建,你会碰到这个例外,可能比来早的日期运行。

在我的情况下,证书验证在7月10日,但模拟器有5月7日的当前日期。

我不知道为什么我的模拟器有它的日期设置为5月7日,因为它本来是要充分利用网络的时候,不过那是另一个时间的问题。

只是觉得我应该共享的情况下,它可以帮助其他人避免浪费几天faffing周围。



Answer 2:

盲目信任所有证书听起来像一个非常糟糕的主意。 你真的应该尝试找出这个问题的原因。 我有一个较旧的Android设备上运行2.3.3同样的错误(较新的Android版本的工作没有任何问题,就像iOS设备):

javax.net.ssl.SSLPeerUnverifiedException: No peer certificate

在SO读取多个不同的相关问题后,我得出的结论,这可能发生两个(或许更多?)的原因:

  • 不正确的安装中间证书的(使用验证证书https://www.digicert.com/help/index.htm )
  • 证书链的顺序不正确

在我的情况下,它是证书的一个不正确的顺序。 举个例子,我张贴从证书为了这个问题,从用户的见解的答复BDC 。 您可以通过执行从终端下面拿到证书顺序:

openssl s_client -connect eu.battle.net:443

(很明显,你自己的服务器替换eu.battle.net)。 在eu.battle.net当时的顺序是这样:

Certificate chain
 0 s:/C=US/ST=California/L=Irvine/O=Blizzard Entertainment, Inc./CN=*.battle.net
   i:/C=US/O=Thawte, Inc./CN=Thawte SSL CA
 1 s:/C=US/O=thawte, Inc./OU=Certification Services Division/OU=(c) 2006 thawte, Inc. - For authorized use only/CN=thawte Primary Root CA
   i:/C=ZA/ST=Western Cape/L=Cape Town/O=Thawte Consulting cc/OU=Certification Services Division/CN=Thawte Premium Server CA/emailAddress=premium-server@thawte.com
 2 s:/C=US/O=Thawte, Inc./CN=Thawte SSL CA
   i:/C=US/O=thawte, Inc./OU=Certification Services Division/OU=(c) 2006 thawte, Inc. - For authorized use only/CN=thawte Primary Root CA

虽然它应该是:

Certificate chain
 0 s:/C=US/ST=California/L=Irvine/O=Blizzard Entertainment, Inc./CN=*.battle.net
   i:/C=US/O=Thawte, Inc./CN=Thawte SSL CA
 1 s:/C=US/O=Thawte, Inc./CN=Thawte SSL CA
   i:/C=US/O=thawte, Inc./OU=Certification Services Division/OU=(c) 2006 thawte, Inc. - For authorized use only/CN=thawte Primary Root CA
 2 s:/C=US/O=thawte, Inc./OU=Certification Services Division/OU=(c) 2006 thawte, Inc. - For authorized use only/CN=thawte Primary Root CA
   i:/C=ZA/ST=Western Cape/L=Cape Town/O=Thawte Consulting cc/OU=Certification Services Division/CN=Thawte Premium Server CA/emailAddress=premium-server@thawte.com

规则是证书的“n”的在链中的发行者应该匹配证书的主题“N + 1”。

一旦我发现这个问题是微不足道的改变服务器和事物的证书顺序立即开始了Android 2.3.3设备上工作。 我想这是很好的,较旧的Android版本都有点讨厌有关证书秩序,但它也是一个噩梦,因为较新的Android版本会自动重新排序的证书。 地狱,即使是旧的iPhone 3GS与证书摸索出的顺序。



文章来源: Android SSL No peer certificate