I have written an API so that my different apps can use it.It simply checks whether app is registered with the server or not.If not then it generates Public/Private keypair,and got a signed certificate by sending CSR to my server. The next time it uses the signed certificate and private key. Initially I have default keystore file in raw ( b/c all my communication is over SSL i.e. initially with default keystore and after registration with user generated keystore)
My API is working fine. The issues I am having are somewhat related to my lack of knowledge or wrong approach and hence I need assistance.
I am using the following class to save/retrieve my Keypair
public class KeyIOHandler { public static void writePublicKeyToPreferences(KeyPair key, Context context) { StringWriter publicStringWriter = new StringWriter(); try { PemWriter pemWriter = new PemWriter(publicStringWriter); pemWriter.writeObject(new PemObject("myapp.PUBLIC KEY", key.getPublic().getEncoded())); pemWriter.flush(); pemWriter.close(); SharedPreferences preferences = context.getSharedPreferences("SHARED_PREFERENCES",0); preferences.edit().putString("RSA_PUBLIC_KEY", publicStringWriter.toString()).commit(); Log.e("Public Key", publicStringWriter.toString()); } catch (IOException e) { Log.e("RSA", e.getMessage()); e.printStackTrace(); } } public static void writePrivateKeyToPreferences(KeyPair keyPair, Context context) { StringWriter privateStringWriter = new StringWriter(); try { PemWriter pemWriter = new PemWriter(privateStringWriter); pemWriter.writeObject(new PemObject("myapp.PRIVATE KEY", keyPair.getPrivate().getEncoded())); pemWriter.flush(); pemWriter.close(); SharedPreferences preferences = context.getSharedPreferences("SHARED_PREFERENCES",0); preferences.edit().putString("RSA_PRIVATE_KEY", privateStringWriter.toString()).commit(); Log.e("Private Key",privateStringWriter.toString()); } catch (IOException e) { Log.e("RSA", e.getMessage()); e.printStackTrace(); } } public static PublicKey getRSAPublicKeyFromString(String publicKeyPEM) throws Exception { publicKeyPEM = stripPublicKeyHeaders(publicKeyPEM); KeyFactory keyFactory = KeyFactory.getInstance("RSA", "SC"); byte[] publicKeyBytes = Base64.decode(publicKeyPEM.getBytes("UTF-8")); X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(publicKeyBytes); return keyFactory.generatePublic(x509KeySpec); } public static PrivateKey getRSAPrivateKeyFromString(String privateKeyPEM) throws Exception { privateKeyPEM = stripPrivateKeyHeaders(privateKeyPEM); KeyFactory fact = KeyFactory.getInstance("RSA", "SC"); byte[] clear = Base64.decode(privateKeyPEM); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(clear); PrivateKey priv = fact.generatePrivate(keySpec); Arrays.fill(clear, (byte) 0); return priv; } public static String stripPublicKeyHeaders(String key) { //strip the headers from the key string StringBuilder strippedKey = new StringBuilder(); String lines[] = key.split("\n"); for (String line : lines) { if (!line.contains("BEGIN PUBLIC KEY") && !line.contains("END PUBLIC KEY") && !isNullOrEmpty(line.trim())) { strippedKey.append(line.trim()); } } return strippedKey.toString().trim(); } public static String stripPrivateKeyHeaders(String key) { StringBuilder strippedKey = new StringBuilder(); String lines[] = key.split("\n"); for (String line : lines) { if (!line.contains("BEGIN PRIVATE KEY") && !line.contains("END PRIVATE KEY") && !isNullOrEmpty(line.trim())) { strippedKey.append(line.trim()); } } return strippedKey.toString().trim(); } public static boolean isNullOrEmpty(String str) { return str == null || str.isEmpty(); } } and by using the following method I am generating my keystore but I am confuse how and where I can store this keystore securely so that i can use it for the rest of app's life.(unless key is stolen). As in shared preferences I cannot store any object, so where to save this keystore.Right now I have static keystore object in my class.(which is worst I know but just to make it working i have made it static)
private boolean addToStore(){ try { Security.insertProviderAt(new org.spongycastle.jce.provider.BouncyCastleProvider(), 1); clientPkcs12 = KeyStore.getInstance("PKCS12"); clientPkcs12.load(null, null); clientPkcs12.setKeyEntry("clientCert", keyPair.getPrivate(), "123456".toCharArray(), chain); } catch(Exception ex){ Log.e("",ex.getCause().getMessage()); } return false; } I have gone through few posts,among them this is noticeable one nelenkov.blogspot but not getting how can I achieve my target or am I wrong at saving keystore? I mean do I have to create keystore every time?