views:

200

answers:

3

I have a mobile application where I would like to store private keys securely. The security requirement implies that it should be very hard for attackers to be able to obtain the private key even if they had unlimited access to the mobile device. In order to achieve this level of security, the application employs symmetric cryptography with a key derived from a passphrase specified by the user and a salt specific to the device.

Ideally, this should be secure enough against a brute-force attack; however there a two limiting factors:

  1. Since the private key must conform to a certain format, the decryption process can test the result of the process to see if it is valid or not. For example, if the private key was to be an RSA private key, the attacker would try various combinations of the passphrase and test to see if he can use the resulting plaintext as a valid RSA private key. Since the RSA private key must encode certain information in a certain way, if the decryption failed, the RSA engine would signal that the key is not valid. This gives the attacker a totally offline way of verifying his attacks. Preferably, the attacker should not be able to tell, without communicating with a server, if his decryption attempt was successful or not.

  2. Since the application runs on a mobile device, the increased complexity of the Key Derivation Function does not help with Key Strengthening since an offline attack that has full access to the mobile device would presumably be undertaken on a more capable device with richer resources. Shortly, any increase in the number of rounds of calculation of the key derivation function would slow down the user experience (which acceptable to a certain limit) but would be immediately thwarted if the attack were to be performed on a desktop computer.

Could anybody offer me a solution to these problems? Specifically, does anybody know an asymmetric cryptography algorithm where the private key can be any random byte sequence (it could be fixed-length sequence, that doesn't matter), and the algorithm would still be able to produce ciphertext?

A: 

The private key for RSA is a fixed-length random byte sequence. You just happened to be looking at an ASCII encoding of it. Just store the key in a non-ASCII format and you should be good.

Wim
Unless the public key is public...
Tom Hawtin - tackline
Are you sure about that? Doesn't the RSA private key encode a very long composite number, along with its prime factors (I know I am simplying, but the exact detail is not important)? If it does then the result is anything but random since the parts have to be consistent with each other (ie. the prime factors should multiply to give the composite number).
paracycle
You're right, it's not *totally* random, some bits will be dependent on others. But this shouldn't be a real problem as long as there are enough independent bits left (and for a private key that should be a rather large amount - I'm pretty sure they don't store both composite numbers and its prime factors, since you can trivialy compute the former by multiplying the latter ones).
Wim
The point Tom Hawtin makes is much more of a problem for you though: since the public key can be derived from the private key, any candidate private key your brute-force method may have discovered can be trivially validated by deriving its public key and comparing it with the known public key!
Wim
Thanks, I see, I hadn't thought of the verification with the public key step. :) You are absolutely right, I could store the bare minimum private key parameters in a file and feed them to the RSA engine when I need to encrypt/decrypt, that way the private key would be random enough, I suppose. However, I still have the problem of the public key being public. Thus, would it be OK if I don't distribute the public key but store it on the server side to match requests? Does that make any sense?
paracycle
It wouldn't be a **public** key anymore ;-) But it would certainly help in your case. Although you could just as well use symmetric encryption then.
Wim
Other than that one server could impersonate users to another server if you used symmetric keys (which may or may not be a threat).
caf
@caf is right. I don't want to go down the symmetric encryption route since any attack on the server would reveal the keys necessary to impersonate **all** the users. I would like to limit any exposure on the server side such as this. I guess the best way is to store **public** keys (which are now public in the sense that it is not a threat, on its own, that these keys are stolen) on the server side and send private keys to the client in an essentially random format (ie no discernible format/pattern).
paracycle
+4  A: 

The security requirement implies that it should be very hard for attackers to be able to obtain the private key even if they had unlimited access to the mobile device.

That's just not possible.

Here's what an attacker can do:

  1. Get the application in a state where the private key must be loaded in memory. Regular use of the application will cause this.
  2. Dump the contents of the memory.
  3. Slide through the memory bits trying all ranges of the known key length.

Since the key is in memory, it doesn't matter what clever scheme you came up with to generate it from pass-phrases and salts. Your application does all the work for the attacker. Classic case of failed security through obscurity.

This is how Blu-Ray was initially cracked. If the user has full access to a memory dump during application use, there's just no way to prevent them from getting the key this way.

Welcome to the world of DRM.

Ben S
Thanks for the rapid response. I am aware of the attack vector that you are talking about and I know the story of how first HD-DVD and then BluRay was cracked. However, that was the reason I said **very hard** and not impossible. The attack that you describe is very non-trivial to perform for a mobile device, however, an easier way for the attacker is to obtain a storage dump and work on that instead of the device itself. That is the problem I am trying to solve, maybe I was not as clear as I should have been. Can you help me out with that?
paracycle
Protecting against adulteration of a device is difficult. Reasonably protecting against theft is not as difficult.
Tom Hawtin - tackline
Are you developing for iPhone/Android by any chance? There's software simulators for those things (and probably for most other popular platforms), which makes it rather trivial to get a memory dump of your running application...
Wim
@Wim: Same goes for Backberry and J2ME devices.
Ben S
iPhone/Android are amongst the mobile platforms that I am targeting. I do realize that the emulators make it extremely simple to get a memory dump, but that attack vector does not really apply to my scenario, since, the attacker cannot copy the application from the device to the emulator (at least the salt specified by the unique device id would change) and even if he did so, he cannot get the software in a state where the private key is in memory without either a brute-force attack or phishing. If that attack is to any of those things, he has no more interest in getting memory dumps anyway.
paracycle
Thought so (just didn't download these yet myself ;-). Pretty sure there's a Symbian simulator too, but I think he gets the point.
Wim
But the private key is the same for all devices, no? The salt only helps then to diversify the *encrypted* private key, but not the in-memory one -- so a hacked private key from the simulator will be the same as that obtained from a real device. It does prevent them to re-encrypt the key into a format your application accepts (but since they can already read your content now, this probably doesn't help you much).
Wim
@Wim: He didn't say that the same private key was used in every device. I have seen that proposed in some schemes, but it's always a stupid idea. It sounds like paracycle isn't one of those completely clueless folks that suggest such a thing; my assumption is that a unique private key is generated for each user, then protected by symmetric encryption.
erickson
What stops them from getting the salt off the device? They can watch the code running in the simulator to find out how you retrieve the salt. Then they can write an app that does the same thing and displays it on the screen and run this on the device. Now in the emulator they modify the memory image of the salt to match the one found on the device and then they let the app decrypt the private key and grab it from memory. Not easy. But simple once they find the right break points.
jmucchiello
You guys are missing the point. He's not trying to hide the private key from a legitimate user of the device (someone who has the passphrase) - he's trying to hide it from someone who has stolen the device from a legitimate user and therefore does *not* have the passphrase, or access to the application in a working state.
caf
@sylvarking and @caf: You guys are perfectly right. I think I should have been more clear in my original question. Each user **does** get a unique private key which is protected by symmetric encryption with a passphrase chosen by the user. Again, it is true that I really am trying to protect against brute-force attack without a legitimate user around. As @caf says, the attacker does **not** have the app in a working state at that point. Other attack vectors (such as phishing the user to enter the passphrase, a spyware/trojan installed on the device, etc.) are not in the scope of my question.
paracycle
Very good answer. The person asking this question doesn't know what he is doing.
Rook
+2  A: 

Modern symmetric ciphers are very resistant to known plaintext attacks. Where attacks have been discovered, they can require many plaintexts, and sometimes the plaintexts have to be adaptively selected.

Here, the attacker has a single, partial plaintext. I'd assume the workload to be essentially a brute-force search of the key space. If the symmetric key is randomly chosen from the entire keyspace, it is not feasible for an attacker to recover the private key from the ciphertext.

Indirect attacks are much more likely.

For example, something as simple as key-logging spyware is enough to defeat the best cryptography. Cold boot memory attacks or core dump analysis could be used too. These risks can be minimized by zero-izing secrets from memory immediately after use, but they can't be eliminated completely.

Since the key in this case is derived from a user-selected password, the effective key space is likely to be much smaller than the full key space. Mitigate that by requiring longer passwords that include all classes of characters. Also, don't discount key strengthening. Usual recommendations are for thousands of iterations of the key derivation function, but even if you can only afford a few hundred, that imposes a significant computation cost on an attacker.

erickson
Thanks for the informed answer. You are absolutely correct that the length/complexity of the passphrase greatly limits the key-space. Howeever, the fact that this is a mobile application makes it harder to enforce longer, or more complex passphrases, since most users would find it impossible to use (imagine having to enter a 10-char alphanumeric passphrase on a multi-tap device you need to sign a response). I do employ key strengthening, but like I said, if the user experience on the device is not slowed down greatly, the extra cost will be relatively small on an attacker working on a desktop.
paracycle
(cont'd) There remains the issue of the attacker being able to **verify** the validity of the decrypted plaintext purely offline. For the brute-force attack to work successfully, attacker should be able to tell if the plaintext is correct or not. Thus if the plaintext (private key) has a pattern (ie. PEM format) or can be fed into a blackbox (the RSA engine) that will fail for invalid plaintext, the attacker can verify the validity of decryption. What I am after is a method which will force the attacker to sign something with the plaintext and send it to the server, to validate the plaintext.
paracycle
I'd sum up the clarifying comments as, "The symmetric key is too small to protect against a brute force attack." Given the constraints on password size and complexity, getting 64 bits worth of entropy sounds like a stretch. Unfortunately, I can't recommend an alternative the involves a server. I don't know of an existing method, and everything I've devised myself seems to expose too much information as it travels over the network. I'll keep thinking about it.
erickson