gpt4 book ai didi

java - Android - 如何以编程方式将证书存储在 keystore 中?

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

我正在做一个金融交易安卓应用程序。它需要 SSL 身份验证,我能够成功完成它(Android 和 Tomcat 之间的握手)。我使用 keytool 和 openSSL 生成服务器和客户端证书。 Tomcat 证书格式为 JKS,android 格式为 BKS。我将这个 BKS 文件存储在 Raw 文件夹中,并按如下方式使用它:

public class NetworkCallSecure extends AsyncTask<String, Void, String> {

ResponseListener responseListener;
Activity activity;
ResultCodes code;

public NetworkCallSecure(Activity activity, ResponseListener responseListener, ResultCodes code) {
this.responseListener = responseListener;
this.activity = activity;
this.code = code;
}

@Override
protected String doInBackground(String... params) {

try{

System.setProperty("http.keepAlive", "false");
HttpsURLConnection .setDefaultHostnameVerifier(new HostnameVerifier() {

public boolean verify(String hostname,
SSLSession session) {
Log.d("HTTPS",hostname+":"+session);
return true;
}
});

char[] passwKey = "mypass".toCharArray();
KeyStore ks = KeyStore.getInstance("BKS");
InputStream in = activity.getResources().openRawResource(
R.raw.client);
InputStream is = activity.getResources().openRawResource(
R.raw.client);
ks.load(in, passwKey);
KeyManagerFactory kmf = KeyManagerFactory.getInstance("X509");
kmf.init(ks, passwKey);

SSLContext context = SSLContext.getInstance("TLS");
context.init(kmf.getKeyManagers(),
new X509TrustManager[] { new MyX509TrustManager(is,
passwKey) }, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(context
.getSocketFactory());

URL url = new URL(params[0]);

HttpsURLConnection connection = (HttpsURLConnection) url
.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/json");
connection.setRequestProperty("Content-Length", "" + Integer.toString(params[1].getBytes().length));
connection.setDoOutput(true);

byte[] outputInBytes = params[1].getBytes("UTF-8");
OutputStream os = connection.getOutputStream();
os.write( outputInBytes );
os.close();

BufferedReader bin = new BufferedReader(new InputStreamReader(
connection.getInputStream()));

StringBuffer sb = new StringBuffer();
String line;
while ((line = bin.readLine()) != null) {
sb.append(line);
}
in.close();
is.close();
return sb.toString();
} catch (Exception e) { // should never happen
e.printStackTrace();
Log.d("Err", e.toString());
}
return "no result";
}

@Override
protected void onPostExecute(String result) {
responseListener.getResponse(result,code);
}
}

我的 Trustmanager 类是:

public class MyX509TrustManager implements X509TrustManager {
X509TrustManager pkixTrustManager;

public MyX509TrustManager(InputStream trustStore, char[] password)
throws Exception {
// create a "default" JSSE X509TrustManager.

KeyStore ks = KeyStore.getInstance("BKS");

ks.load(trustStore, password);

TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
tmf.init(ks);

TrustManager tms[] = tmf.getTrustManagers();

/*
* Iterate over the returned trustmanagers, look for an instance of
* X509TrustManager. If found, use that as our "default" trust manager.
*/
for (int i = 0; i < tms.length; i++) {
if (tms[i] instanceof X509TrustManager) {
pkixTrustManager = (X509TrustManager) tms[i];
return;
}
}

/*
* Find some other way to initialize, or else we have to fail the
* constructor.
*/
throw new Exception("Couldn't initialize");
}

public void checkClientTrusted(X509Certificate[] arg0, String arg1)
throws CertificateException {
// TODO Auto-generated method stub
try {
pkixTrustManager.checkClientTrusted(arg0, arg1);
} catch (CertificateException excep) {
// do any special handling here, or rethrow exception.
}

}

public void checkServerTrusted(X509Certificate[] arg0, String arg1)
throws CertificateException {
// TODO Auto-generated method stub
try {
pkixTrustManager.checkServerTrusted(arg0, arg1);
} catch (CertificateException excep) {
/*
* Possibly pop up a dialog box asking whether to trust the cert
* chain.
*/
}
}

public X509Certificate[] getAcceptedIssuers() {
// TODO Auto-generated method stub
return pkixTrustManager.getAcceptedIssuers();
}
}

现在我想使用这个 HTTPS 连接注册用户。该过程是从用户那里获取详细信息并将其发送到服务器。服务器将验证这些详细信息并在用户手机上发送确认 PIN(在用户详细信息中获取此 MSISDN)。用户将输入此 PIN,服务器将验证 PIN 是否相同。用户通过验证后,客户端应用程序(用户手机)将生成 CSR 并将其发送到服务器。服务器将使用此 CSR 生成证书并将其发送到客户端(移动应用程序)。现在我的问题是我想将此证书存储在只有我的应用程序可以访问此证书的地方。我正在尝试使用此将其保存在原始文件夹中的 BKS 文件中:

private boolean storeCertInKeystore(byte[] cert) {
try {
InputStream is = getResources().openRawResource(
R.raw.client);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream certstream = new ByteArrayInputStream(cert);
X509Certificate certificate = (X509Certificate) cf.generateCertificate(certstream);
KeyStore keyStore = KeyStore.getInstance("BKS");
keyStore.load(is, "mypass".toCharArray());
keyStore.setCertificateEntry("mycert", certificate);


Log.d("My App Cert: ", "true");
return true;
} catch(Exception e) {
e.printStackTrace();
}
return false;
}

此代码成功运行但无法将证书存储在 BKS 文件中。我尝试了另一种方式来描述 here但无法成功。 (我想稍后在我的应用程序中使用此证书进行客户端身份验证)我的问题是问。如何存储此证书以便它只能由我的应用程序访问?当用户注册到期时,我也可以删除这个证书。

请帮助并提前致谢。

最佳答案

  • 您的问题不在于 keystore 本身,而在于您尝试存储新客户端的文件的位置证书!
  • “RAW 文件夹”是您安装的应用程序包的一部分。所以您可以“虚拟”访问它,并且只能读取,不能写入!
  • 如果您希望您的 keystore 是私有(private)的,您最好的选择是您的application sandboxed-private-folder(内部存储).
    你不能在 RAW 文件夹中写入,但你可以在你的应用程序私有(private)文件夹中写入。
  • link您提供的存储/写入位置在事实上私有(private)文件夹。所以它对你不起作用,因为你是尝试“写入原始文件夹
  • 你可能已经知道了,但是你可以复制你的文件(R.raw.client)从“原始文件夹”到您的应用程序私有(private)文件夹。这样,您只使用一个 keystore 文件(可读和可写)。

关于java - Android - 如何以编程方式将证书存储在 keystore 中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33706984/

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