[英]Android - How to store certificate in keystore programmatically?
I am making a financial transaction android app. 我正在制作一个金融交易Android应用程序。 It requires SSL authentication and I successfully able to complete it(handshake between Android and Tomcat).
它需要SSL身份验证,我成功完成了它(Android和Tomcat之间的握手)。 I used keytool and openSSL to generate Server and client certificates.
我使用keytool和openSSL生成服务器和客户端证书。 Tomcat certifcate format is JKS and android formate is BKS.
Tomcat certifcate格式是JKS,而android formate是BKS。 I stored this BKS file in Raw folder and use this as follows:
我将此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);
}
}
My Trustmanager class is: 我的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();
}
}
Now I want to register user using this HTTPS connection. 现在我想使用此HTTPS连接注册用户。 The process is get details from user and send it to server.
该过程是从用户获取详细信息并将其发送到服务器。 Server will verify these details and send confirmation PIN on user mobile (got this MSISDN in user details).
服务器将验证这些详细信息并在用户移动设备上发送确认PIN(在用户详细信息中获取此MSISDN)。 User will enter this PIN and server will verify that PIN is same.
用户将输入此PIN,服务器将验证PIN是否相同。 After user is verified client app (user mobile) will generate a CSR and send it to server.
用户验证后,客户端应用程序(用户移动)将生成CSR并将其发送到服务器。 Server will generate Certificate using this CSRand send it to client (mobile app).
服务器将使用此CSR生成证书并将其发送到客户端(移动应用程序)。 Now my problem is I want to store this certificate where only my App can access this certificate.
现在我的问题是我想存储此证书,只有我的应用程序可以访问此证书。 I am trying to save this in my BKS file in raw folder using this:
我试图将此保存在我的原始文件夹中的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;
}
This code runs successfully but could not store cert in BKS file. 此代码成功运行,但无法在BKS文件中存储证书。 I tried another way describe here but could not succeed.
我尝试另一种方式描述了这里 ,但未能成功。 (I want to use this certificate later in my app for client authentication) My Question is Q. How can I store this certificate so it can be only accessible by my app?
(我想稍后在我的应用程序中使用此证书进行客户端身份验证)我的问题是问:如何存储此证书,以便只能通过我的应用程序访问? And also I can delete this certificate when user registration expires.
此外,我还可以在用户注册过期时删除此证书。
Please help and thanks in advance. 请提前帮助和感谢。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.