서버에 연결하는 앱을 만들고 싶습니다. 이 서버는 SSL 클라이언트 인증을 사용합니다. 앱 사용자는 인증서를 선택하고 브라우저 앱에 구현 된 것처럼 인증서의 사용을 허용 할 수 있어야합니다.Android 4.x에서 SSL 클라이언트 인증
브라우저 앱에서 인증이 예상대로 작동하므로 내가 사용하는 인증서가 유효합니다.
javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException:
SSL handshake terminated: ssl=0x2a2d3b38:
Failure in SSL library, usually a protocol error
error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure
(external/openssl/ssl/s3_pkt.c:1290 0x2a2df880:0x00000003)
내가 내 구현을위한 안드로이드 문서를 따라하려고 :
나는 다음과 같은 오류가 내 응용 프로그램에 연결을 시도
. 핸드 쉐이크의 캡처public class ClientCertificateActivity extends Activity implements
KeyChainAliasCallback {
protected static final String TAG = "CERT_TEST";
private String alias;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
choseCertificate();
LinearLayout layout = new LinearLayout(this);
Button connectToServer = new Button(this);
connectToServer.setText("Try to connect to Server");
connectToServer.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
connectToServer.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
connectToServer();
}
});
layout.addView(connectToServer);
addContentView(layout, new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
}
protected void connectToServer() {
final Context ctx = this;
new AsyncTask<Void, Void, Boolean>() {
private Exception error;
@Override
protected Boolean doInBackground(Void... arg) {
try {
PrivateKey pk = KeyChain.getPrivateKey(ctx, alias);
X509Certificate[] chain = KeyChain.getCertificateChain(ctx,
alias);
KeyStore keyStore = KeyStore.getInstance("AndroidCAStore");
TrustManagerFactory tmf = TrustManagerFactory
.getInstance(TrustManagerFactory
.getDefaultAlgorithm());
tmf.init(keyStore);
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);
URL url = new URL("https://usecert.example.com/");
HttpsURLConnection urlConnection = (HttpsURLConnection) url
.openConnection();
urlConnection.setSSLSocketFactory(context
.getSocketFactory());
InputStream in = urlConnection.getInputStream();
return true;
} catch (Exception e) {
e.printStackTrace();
error = e;
return false;
}
}
@Override
protected void onPostExecute(Boolean valid) {
if (error != null) {
Toast.makeText(ctx, "Error: " + error.getMessage(),
Toast.LENGTH_LONG).show();
return;
}
Toast.makeText(ctx, "Success: ", Toast.LENGTH_SHORT).show();
}
}.execute();
}
protected void choseCertificate() {
KeyChain.choosePrivateKeyAlias(this, this,
new String[] { "RSA", "DSA" }, null, "m.ergon.ch", 443, null);
}
@Override
public void alias(String alias) {
this.alias = alias;
}
}
이 예외가 여기에 urlConnection.getInputStream();
던져됩니다 : 여기
- Unifying Key Store Access in ICS
- HttpsURLConnection 내 샘플 활동의 코드 서버와 C 사이 lient.
의견과 제안을 보내 주셔서 감사합니다.
감사합니다. 그런데 어떻게 내 개인 키로 그러한 KeyManager를 만들 수 있습니까? 이 부분은 [Android Doc for HttpsURLConnection] (http://developer.android.com/reference/javax/net/ssl/HttpsURLConnection.html)의 예에서 누락되었습니다. – surffan
직접적인 방법은없는 것처럼 보입니다. 이. 'PrivateKey'와 일부 하드 코드 된 별칭을 반환하려면'X509KeyManager'를 구현해야합니다. 서버 관련 메소드를 구현할 필요는 없습니다. http://developer.android.com/reference/javax/net/ssl/X509KeyManager.html –
샘플 코드에 대한 업데이트 된 답변보기 –