1. ホーム
  2. android

[解決済み] Android SSL - ピア証明書なし

2022-02-27 04:01:16

質問

このコードを実行すると、必ず「No Peer Certificate」エラーが発生します。

SSL証明書は有効で、Namecheap(PositiveSSL)から購入したものです。その前にCA crtがあり、Androidのブラウザで問題なく開けます。

HTTPサーバー:nginx

コード

public void postData() {

// Add your data
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);

nameValuePairs.add(new BasicNameValuePair("string", "myfirststring"));

try {

   HttpPost post = new HttpPost(new URI("https://example.com/submit"));
    post.setEntity(new UrlEncodedFormEntity(nameValuePairs));

    KeyStore trusted = KeyStore.getInstance("BKS");
    trusted.load(null, "".toCharArray());
    SSLSocketFactory sslf = new SSLSocketFactory(trusted);
    sslf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

    SchemeRegistry schemeRegistry = new SchemeRegistry();
    schemeRegistry.register(new Scheme ("https", sslf, 443));
    SingleClientConnManager cm = new SingleClientConnManager(post.getParams(),
            schemeRegistry);

    HttpClient client = new DefaultHttpClient(cm, post.getParams());

    // Execute HTTP Post Request
    @SuppressWarnings("unused")
    HttpResponse result = client.execute(post);

} catch (ClientProtocolException e) {
    // TODO Auto-generated catch block
    Log.e(TAG,e.getMessage());
    Log.e(TAG,e.toString());
    e.printStackTrace();
} catch (IOException e) {
    // TODO Auto-generated catch block
    Log.e(TAG,e.getMessage());
    Log.e(TAG,e.toString());
    e.printStackTrace();
} catch (URISyntaxException e) {
        // TODO Auto-generated catch block
    Log.e(TAG,e.getMessage());
    Log.e(TAG,e.toString());
    e.printStackTrace();
    } catch (KeyStoreException e) {
        // TODO Auto-generated catch block
        Log.e(TAG,e.getMessage());
        Log.e(TAG,e.toString());
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        // TODO Auto-generated catch block
        Log.e(TAG,e.getMessage());
        Log.e(TAG,e.toString());
        e.printStackTrace();
    } catch (CertificateException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        Log.e(TAG,e.toString());
        Log.e(TAG,e.getMessage());
    } catch (KeyManagementException e) {
        // TODO Auto-generated catch block
        Log.e(TAG,e.getMessage());
        Log.e(TAG,e.toString());
        e.printStackTrace();
    } catch (UnrecoverableKeyException e) {
        // TODO Auto-generated catch block
        Log.e(TAG,e.getMessage());
        Log.e(TAG,e.toString());
        e.printStackTrace();
    }
}

Adbログキャット :

01-10 15:44:34.872: E/myfirstapp(572): No peer certificate
01-10 15:44:34.872: E/myfirstapp(572): javax.net.ssl.SSLPeerUnverifiedException: No peer certificate
01-10 15:44:34.883: W/System.err(572): javax.net.ssl.SSLPeerUnverifiedException: No peer certificate
01-10 15:44:34.883: W/System.err(572):  at org.apache.harmony.xnet.provider.jsse.SSLSessionImpl.getPeerCertificates(SSLSessionImpl.java:137)
01-10 15:44:34.883: W/System.err(572):  at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:93)
01-10 15:44:34.908: W/System.err(572):  at org.apache.http.conn.ssl.SSLSocketFactory.createSocket(SSLSocketFactory.java:381)
01-10 15:44:34.908: W/System.err(572):  at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:165)
01-10 15:44:34.908: W/System.err(572):  at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164)
01-10 15:44:34.914: W/System.err(572):  at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119)
01-10 15:44:34.914: W/System.err(572):  at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:360)
01-10 15:44:34.914: W/System.err(572):  at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)
01-10 15:44:34.914: W/System.err(572):  at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)
01-10 15:44:34.914: W/System.err(572):  at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465)
01-10 15:44:34.933: W/System.err(572):  at com.giggsey.myfirstapp.myfirstappIntent.postData(myfirstappIntent.java:126)
01-10 15:44:34.933: W/System.err(572):  at com.giggsey.myfirstapp.myfirstappIntent.onReceive(myfirstappIntent.java:77)
01-10 15:44:34.933: W/System.err(572):  at android.app.ActivityThread.handleReceiver(ActivityThread.java:2118)
01-10 15:44:34.945: W/System.err(572):  at android.app.ActivityThread.access$1500(ActivityThread.java:122)
01-10 15:44:34.945: W/System.err(572):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
01-10 15:44:34.952: W/System.err(572):  at android.os.Handler.dispatchMessage(Handler.java:99)
01-10 15:44:34.952: W/System.err(572):  at android.os.Looper.loop(Looper.java:137)
01-10 15:44:34.962: W/System.err(572):  at android.app.ActivityThread.main(ActivityThread.java:4340)
01-10 15:44:34.962: W/System.err(572):  at java.lang.reflect.Method.invokeNative(Native Method)
01-10 15:44:34.962: W/System.err(572):  at java.lang.reflect.Method.invoke(Method.java:511)
01-10 15:44:34.972: W/System.err(572):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
01-10 15:44:34.972: W/System.err(572):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
01-10 15:44:34.981: W/System.err(572):  at dalvik.system.NativeStart.main(Native Method)

解決方法は?

この質問にはすでに回答がありますが、2.3.3を実行している古いAndroidデバイスで同じエラーが発生したため、回答する価値があると考えました。

javax.net.ssl.SSLPeerUnverifiedException: No peer certificate

SOでいくつかの異なる関連する質問を読んだ後、私はこれが2つ(もしかしたらそれ以上)の理由で起こりうるという結論に達しました。

  • 中間証明書のインストールが適切でない
  • 証明書チェーンの順序が正しくない

私の場合、証明書の順番が正しくないことが原因でした。例として、以下から証明書の順番を掲載します。 この質問 ユーザーからの洞察に満ちた回答とともに ビーディーシー . ターミナルから以下のように操作することで、証明書の発注を行うことができます。

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/[email protected]
 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/[email protected]

チェイン内の証明書 "n" の発行者は、証明書 "n+1" のサブジェクトと一致しなければならないという規則があります。

問題を発見した後は、サーバー上で証明書の順番を変更するのは簡単で、すぐにAndroid 2.3.3デバイス上で動作するようになりました。古いバージョンのAndroidは証明書の順番にうるさいのでいいのですが、新しいバージョンのAndroidは証明書の順番を自動的に変えてしまうので、悪夢のようでした。古いiPhone 3GSでさえ、証明書の順番が狂っているのに動いたのですから、地獄です。