4

I'm new to Android development and implementing SSLSockets. After doing some digging I was able to setup a simple server/client that is working. The implementation I feel could use some work and stumped on how to load in the password to the keystore without having it in plain text. Here is some code that is on the client side. As you can see I have the password hard coded into a local var. Is there a better way to load in the keystore password so I do not have it in plain text in the code?

    char [] KSPASS = "password".toCharArray();
    char [] KEYPASS = "password".toCharArray();
    try {
        final KeyStore keyStore = KeyStore.getInstance("BKS");
        keyStore.load(context.getResources().openRawResource(R.raw.serverkeys), KSPASS);

        final KeyManagerFactory keyManager = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        keyManager.init(keyStore, KEYPASS);

        final TrustManagerFactory trustFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        trustFactory.init(keyStore);

        sslContext = SSLContext.getInstance("TLS");
        sslContext.init(keyManager.getKeyManagers(), trustFactory.getTrustManagers(), null);
        Arrays.fill(KSPASS, ' ');
        Arrays.fill(KEYPASS, ' ');

        KSPASS = null;
        KEYPASS = null;

Update:

It turns out the client did not need to know the keystore password at all. I've modified the code to pass null in as the password. So far initial tests have worked with communication to the server. On the server side I still load the keystore password.

        final KeyStore keyStore = KeyStore.getInstance("BKS");
        keyStore.load(context.getResources().openRawResource(R.raw.serverkeys), null);

        final KeyManagerFactory keyManager = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        keyManager.init(keyStore, null);

        final TrustManagerFactory trustFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        trustFactory.init(keyStore);

        sslContext = SSLContext.getInstance("TLS");
        sslContext.init(keyManager.getKeyManagers(), trustFactory.getTrustManagers(), null);
mdbox
  • 412
  • 5
  • 12

2 Answers2

8

Well this is not an easy problem to begin with.

You could for example request the password from the user on application startup so that the password is not hardcoded in your code.I think this is the most secure approach.

If this is not possible, then your problem arises if someone has access to the jars and "sees" the code and subsequently the password. You could delegate to the user protecting these jars.

If this is not possible then you could encrypt the password and store it somewhere. Then in your code you hard code the key to decrypt the password. So someone looking into the jar can not see your real password.Only the decryption key. Of course if one put real effort he could get the key and try to find where the password is located and decrypt it and get the key but it requires more effort to do.

In the end it depends on what security requirements you have

Cratylus
  • 52,998
  • 69
  • 209
  • 339
  • Java is easy to decompile and read. And when you follow the calls you'd see those extra encryption parts pretty fast. But its a risk he should probably take as a not encrypted network stream is way more dangerous than this. – lhw Sep 16 '11 at 20:24
  • Well, as mentioned if the attacker does the extra effort he can eventually get the key.The best option is to ask the user for the password on start up. – Cratylus Sep 16 '11 at 20:28
  • The comment was meant as additional information for the asker. I should have pointed that out. – lhw Sep 16 '11 at 20:46
  • Let me clarify a little. This is not a password the user would know. The idea is to not have plain text transmission from the client to the server. So I used the command keytool to create a certificate, gave it a keystore password and added a key and gave that another password. The application is not sending sensitive data but I still did not want plain text. Does signing the Android app make it harder to decompile? – mdbox Sep 16 '11 at 21:53
  • Even if you obfuscate the code, the various constant variables in your programs should be visible (otherwise you program would not run).You could combine encryption of the password and then obfuscating the code. But then you must also take into consideration where/how to store the decryption key – Cratylus Sep 17 '11 at 07:05
  • Thanks for the help. As for the client goes I never should have loaded the password. I've added an update to the original post. – mdbox Sep 17 '11 at 08:25
1

If you truly want to protect the users credentials then you must ask them to verify their identity whenever you want access to the credentials. However most users will get annoyed if you ask them for their password every time they login, so you as the developer must decide how much you care about security vs providing a simple easy interface for your users.

One option you could consider is to store the passwords but to encrypt the password using a PIN provided by the user. Then whenever the user wants to access their password they simply provide the PIN, which you use to decrypt the password.

slayton
  • 20,123
  • 10
  • 60
  • 89