0

I have a java app on Android that needs to be able to communicate with a web server over ssl using an client x509 certificate (for encryption negotiation) - the private key is in the java keystore to which access is protected by a passphrase.

Now the best part: I don't want to store passphrase in app, instead I want to send this passphrase via secure connection from server ... vicious circle.

What possibilities do I have? It looks like both sides need their own keypairs or symmetric key for encryption, or I need to send a passphrase via unsecured connection which anyone can sniff ;/

I can deploy the cert after first installation and set keystore passphrase to user encrypted password for double protection, this way the client can ensure that the cert was not tampered with during app usage.

how can my app check if it can trust given cert?

The Authority certificate is cross-signed by IdenTrust ("DST Root CA X3" Root CA)

case:

  • cert is in app
  • app is deployed on device
  • server is showing cert to app on negotiation
  • app is comparing cert (validating by it's copy)
  • in moment when app is reading cert from file the client need to be sure that cert was not tampered (lets assume that we do spoofing cert on server and on client site simultaneously to enforce data exchange in app)
6
  • Usually I don't ask questions like this, but why do you want to encrypt the keystore with a server-provided password? What is the problem you are trying to solve by doing that? Commented Jun 17, 2016 at 3:00
  • 1
    this forum is puristic one or about safety? can you stop editing ?
    – ceph3us
    Commented Jun 17, 2016 at 3:01
  • "insurance for client that server is the right one" -- I don't understand, that's the whole point of ssl server certificates. The SSL handshake already proves the identity of the server. Commented Jun 17, 2016 at 3:04
  • 1
    I think you are overthinking your problem :) Use the server certificate from a public CA.
    – Limit
    Commented Jun 17, 2016 at 3:35
  • Since this question started out with a homebrew solution that made no sense, and then we later dug out the OP's actual motivation, I feel this needs a link to the XY problem. Commented Jun 17, 2016 at 4:35

1 Answer 1

3

Update in response to your edits in the question

You are correct that validating a cert up to the trusted root is not 100% foolproof. What it guarantees that a trusted CA issued this cert to the domain that you are communicating with (because you can check that the URL in the cert matches the URL that you are establishing the SSL connection with). This was how SSL was designed to work. If that's not good enough and you don't fully trust the CAs in the Android trust store, then there are still things you can do.

It sounds like what you are describing is Certificate Pinning. Here is a guide to certificate pinning by OWASP, which even has a section about Android. The idea is that you include either the public key or a hash of the full certificate of the root CA, intermediate CA, or server cert in the source code of your app. Since all Android apps get code-signed at build-time, you can be confident that the "pinned" public key will arrive at the device un-tampered. Unless the device is rooted (more on that below), you should be confident that it will remain un-tampered.

It's good that you're thinking about this very carefully. That's good. But, as @Limit said,

I think you are overthinking your problem :)

You are not the first person to think about this problem, and there are standard ways to solve it. You are making things much more complicated by trying to invent your own solution. A chain of signatures leading back to a cert in the OS trust store (or a pinned key if you want to go the extra mile) really is enough to guarantee that the certificate is real.


About rooted devices, you said:

nova days [now a days] even EPROMS are writable ???? if you can write into memory there is no such thing like immutability :)

besides rooted device is vulnerable for fs files altering

If your app is running on a rooted device (either rooted intentionally by the user, or by malware) then all guarantees and security proofs are off. There are some tricks you can do, but they are security theater at best. As far as real security goes, it's game over. I'm sorry but you're just going to have to accept that, unless you want to enter into an arms race with rootkit authors - which is well outside the scope of this site.

I also want to point out that while possible, the attack you're alluding to is very advanced. You can add code to your app to check the integrity of the binary against the code-signing signature, and refuse to run if the check fails. Here are some links from a quick google search:

With root access to the device, it is possible for a hacker to remove this check from your binary, but this will not happen from casual drive-by malware. It requires expert hackers to spend weeks reverse engineering your app. The kind of experts that you only find in government spy agencies and organized crime. It's time to define your threat model: are you worried that your app will be attacked by nation-states or organized crime? Yes / No?

  • No: then don't worry about it, doing certificate pinning and a runtime self-test of the code-signing will protect you even on rooted devices.

  • Yes: then stop getting advice from random people on the internet and go hire a real security consultant!


Your use-case seems a little strange. It sounds like you are trying to re-invent SSL, rather than using SSL the way it was designed.

In SSL, the server always presents a certificate to prove that it is the right server. The point of mutually-authenticated SSL (where both the server and the client have certificates) is for the device to prove to the server that it is the right device. Having the server send the client a key to decrypt the client cert is a bit like having the server prove to itself that it is the right server. ??


How does the client trust the server's certificate?

The client should trust the server's certificate only if it chains back to a root CA cert that is in the Java Keystore. If your server's certificate was issued by a public CA (ie you bought it from Digicert, or Verisign, etc) then the root should already be in the Android keystore. If it was issued by a private CA, then the right thing to do is to include the root CA's certificate in the app resources and add it to the Java Keystore on the app's first run. (This is safe because the app .apk is code signed, so the cert can not be modified.)

All of this should be handled automatically by Android's SSL libraries. If you are getting exceptions about not trusting the server's certificate, then try adding the root CA cert to the Android trust store.

Inventing your own method of establishing trust by having the server send a decryption key is almost certainly wrong, and is almost certainly more work.


For more reading, please see:

How does SSL/TLS work?

(I know it's a lot of text, but it is a very good reference)

4
  • 1
    [OT] IMHO the general question of trust has no really objective exact answers, not only in crypto but everywhere in life as well. For humans could at times make errors which could then be exploited by others or there are corrupted persons at certain important locations of the transactions. For communications that are top secret, end-to-end encryption with carefully scrutinized software and taking care of many other relevant protection measures, e.g. those against emission risks, would in my personal opinion be an absolute necessity in view of the universal surveillance. Commented Jun 17, 2016 at 6:52
  • @Mok-KongShen Agreed, security is relative, "Is it secure?" is not a Yes/No, it's a scale. Continuing your thought: you also can't trust the developers either; you should only be using apps that you (or your organization) developed, compiled with compilers that you (or your organization) developed, on OSes and hardware that you (or your organization) developed. Does that mean end-users should give up and not bother? No, of course not, but they are going to have to settle for something lower on the security scale. Commented Jun 17, 2016 at 14:38
  • 1
    Well the answer is that one should do the best that is in one's capability (within one's budget, etc.) and always keep in mind that the probability of insecurity could never be reduced to zero. cf. one's health. With time and advancement of technology ever larger number of refined or new attacks on the security of the people crop up, e.g. GPS-spoofing. Commented Jun 17, 2016 at 15:04
  • @Mok-KongShen Yup, agreed. Commented Jun 17, 2016 at 15:09

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .