gpt4 book ai didi

android - Android 4.x 中的 SSL 客户端身份验证

转载 作者:塔克拉玛干 更新时间:2023-11-02 20:03:04 25 4
gpt4 key购买 nike

我想创建一个连接到服务器的应用程序。此服务器使用 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)

我尝试按照 android 文档进行实现。

这是我的示例 Activity 的代码:

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();

这是服务器和客户端之间握手的捕获。 Network capture of the SSL Handshake

感谢您的任何建议和提示。

最佳答案

您永远不会使用您的私钥初始化 KeyManager,因此客户端身份验证无法获取它。

您必须实现 X509KeyManager 才能返回您的私钥和一些硬编码的别名。这是来自常用电子邮件应用程序 (ICS+) 的一个以供引用。您可能需要对其进行一些修改,但它应该很容易理解:基本上它只是将 key 、别名和证书链保存到字段中并通过适当的方法返回它们(StubKeyManager 只是抛出异常未实现和不需要的方法):

public static class KeyChainKeyManager extends StubKeyManager {
private final String mClientAlias;
private final X509Certificate[] mCertificateChain;
private final PrivateKey mPrivateKey;

public static KeyChainKeyManager fromAlias(Context context, String alias)
throws CertificateException {
X509Certificate[] certificateChain;
try {
certificateChain = KeyChain.getCertificateChain(context, alias);
} catch (KeyChainException e) {
logError(alias, "certificate chain", e);
throw new CertificateException(e);
} catch (InterruptedException e) {
logError(alias, "certificate chain", e);
throw new CertificateException(e);
}

PrivateKey privateKey;
try {
privateKey = KeyChain.getPrivateKey(context, alias);
} catch (KeyChainException e) {
logError(alias, "private key", e);
throw new CertificateException(e);
} catch (InterruptedException e) {
logError(alias, "private key", e);
throw new CertificateException(e);
}

if (certificateChain == null || privateKey == null) {
throw new CertificateException("Can't access certificate from keystore");
}

return new KeyChainKeyManager(alias, certificateChain, privateKey);
}

private KeyChainKeyManager(
String clientAlias, X509Certificate[] certificateChain,
PrivateKey privateKey) {
mClientAlias = clientAlias;
mCertificateChain = certificateChain;
mPrivateKey = privateKey;
}


@Override
public String chooseClientAlias(String[] keyTypes, Principal[] issuers, Socket socket) {
return mClientAlias;
}

@Override
public X509Certificate[] getCertificateChain(String alias) {
return mCertificateChain;
}

@Override
public PrivateKey getPrivateKey(String alias) {
return mPrivateKey;
}
}

关于android - Android 4.x 中的 SSL 客户端身份验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13525445/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com