4

Androidアプリケーションをサーバーに安全に接続するためにJavaのSSLSocketを使用しています。証明書はトラストストアにあります。ただし、トラストストアへのパスコードは接続に必要なようで、現在デバイスにハードコードされています。PKI についてはよくわかりませんが、安全ではないようです。私はトラストストアを raw リソース フォルダー内のアプリケーションにバンドルしています。アプリケーションが TLS を使用してサーバーに安全に接続できるようにするためのより良い方法はありますか? 私はTLS / SSLに非常に慣れていないので、助けや推奨事項をいただければ幸いです。

これがコードのクライアント側です。

        store = KeyStore.getInstance("BKS"); 
        InputStream in = appcontext.getResources().openRawResource(R.raw.truststore);
        store.load(in, "PASSWORD".toCharArray());

        TrustManagerFactory tmf = TrustManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        tmf.init(store);
        sslcontext = SSLContext.getInstance("TLS");
        sslcontext.init(null, tmf.getTrustManagers(), new SecureRandom());

        SSLSocketFactory sslsocketfactory = sslcontext.getSocketFactory();

        // connect to socket
        SSLSocket sslsocket = (SSLSocket) sslsocketfactory.createSocket(
                "192.168.1.16", 9999);
4

2 に答える 2

5

Android では試していませんが、プレーンな Java での動作は次のとおりです。

ここではキーストアをトラストストアとして使用しているため、(うまくいけば) 秘密鍵や秘密の素材は含まれていません。この場合、パスワードの目的は、ストアの整合性を確認することです。

Keystore.load(InputStream, char[])ドキュメントから:

キーストアのロックを解除するため (たとえば、キーストアがハードウェア トークン デバイス上に存在する場合)、またはキーストア データの整合性をチェックするために、パスワードを指定することができます。整合性チェック用のパスワードが指定されていない場合、整合性チェックは実行されません。

パスワードとして使用するかnull(この場合、常に証明書をロードできます)、またはchar実際のパスワードで null 以外の配列を使用します (この場合、誤ったパスワードは「java.io. IOException: キーストアが改ざんされたか、パスワードが正しくありませんでした")。

ここでパスワードを使用するのは、セキュリティを強化するためです (トラストストアが改ざんされるのを防ぐため)。そうは言っても、このトラストストアとこのアプリケーションの両方をバンドルしている場合、トラストストアを置き換えることができる攻撃者は、いずれにせよ (逆コンパイルによって) パスワードへのアクセスを取得する可能性があります。(私は Android アプリの配布にあまり詳しくありませんが、アプリが署名されている場合、トラストストアなどの生のリソースを改ざんすると署名も無効になる可能性があるため、この保護を行うより現実的な方法かもしれません。それ以外の場合は、毎回ユーザーにトラストストアのパスワードを入力するように求めることができると思いますが、それは非現実的です。)


それは実際にはあなたの質問の一部ではありませんが、SSL/TLS 接続を保護するには、サーバーから送信された証明書が、到達しようとしていたホスト名に対して有効であることも確認する必要がありますSSLSocket sslsocket = (SSLSocket) sslsocketfactory.createSocket("192.168.1.16", 9999);

これは、Javaのこの質問で最近議論されました。(残念ながら、新しい Java 7 API を使用して Android でこれを自動的に行うことはできないため、証明書をもう少し手動で確認する必要があります。この最近の質問にも興味があるかもしれません。)


編集(コメントに従って):

誰かがアプリケーションを再コンパイルし、パスコードとトラストストアを取得し、それを使用してサーバーに接続することを懸念しています。可能であれば、そもそも TLS の目的を無効にします。

このコメントから、トラストストアの目的を理解しているかどうかは明らかではありません (たとえば、この質問を参照してください)。

クライアント アプリのトラストストアの目的は、サーバーに対してアプリを認証することではなく、クライアントが接続先のサーバーの ID を確認できるようにすることです。 MITM 攻撃者。サーバーがアプリ/クライアント/ユーザーをどのように信頼するかではなく、アプリがサーバーをどのように信頼するかが重要です。

アプリ ユーザーをサーバーに対して認証することが、キーストアの目的です。これは、ユーザーの認証には問題ありません (ただし、各ユーザーが異なる証明書を持っていれば、より意味があります)。アプリからのみ接続できるようにすることは、もう 1 つの、はるかに難しい問題です (クライアント ハードウェアを常に完全に制御できない場合、失われた原因になります)。アプリで一般的なクライアント証明書を使用することで、少し時間稼ぎができるかもしれませんが、クライアント コードを入手した人なら誰でも、最終的には確実にリバース エンジニアリングを行うことができます。私はそれにあまり時間をかけません。次の質問に興味があるかもしれません:

于 2013-08-05T22:53:38.090 に答える