4

Storing a password in an application's memory is risky. The OS may write a portion of memory to disk as a swap file. Processes may access each others' memory, even though they shouldn't. (More)

I'm developing a deterministic password generator with Java and I'm wondering what's the best way to handle the master key in memory. There's going to be periods of time where the application needs to "remember" the master key, before it can overwrite it in memory. I thought about encrypting the master key in memory and writing the randomly generated decryption key to disk. When the master key is no longer needed, the app would attempt to overwrite both the file on disk and the encrypted master key. This approach would at least provide some security against someone later uncovering an old swap file. Does it make sense? Should I do something else?

What are good practices to reduce data lifetime of passwords and cryptographic keys in memory?

7
  • Do you have a specific programming language or environment in mind?
    – Sjoerd
    Commented Jan 13, 2017 at 13:24
  • Java, for all OS's. Edited OP.
    – bkoodaa
    Commented Jan 13, 2017 at 13:27
  • Have you looked into using platform's TPM module/method? For example, Android has KeyStore, iOS has Keychain, Windows has DPAPI, and some Linux distros have keyrings. Commented Jan 13, 2017 at 13:55
  • Java has a keystore.
    – Walfrat
    Commented Jan 13, 2017 at 15:13
  • Are you asking in a general application ? web application, A desktop application, mobile application ? For a web application I won't bother to do more than let the GC collect the String after i don't use it. Desktop/Mobile however may need more than this.
    – Walfrat
    Commented Jan 13, 2017 at 15:18

5 Answers 5

5

In Java, it is recommended that a char[] is used for sensitive data instead of a String object. This makes it possible to overwrite the data when done with it, something that is not possible with the immutable String object.

4

What are good practices to reduce data lifetime of passwords and cryptographic keys in memory?

Encrypt your swap file/partition. Then you wouldn't need to worry about leaking passwords from swap.

If you write the program, then you should also use system features that prevents certain parts of the memory from being paged out, using mlock() or mmap() with MAP_LOCKED in Linux or VirtualLock() in Windows.

Many Linux systems nowadays are configured so that unless you're root or have ptrace permission, you cannot directly read/write to other process of the same user unless the other process is a child process of the tracing process (ptrace_scope = 1). If you need better security, you can also configure so that ptrace child is only possible by root or processes with CAP_SYS_PTRACE capability (ptrace_scope = 2) or to disable ptrace entirely (ptrace_scope = 3). On Windows, this permission is called SE_DEBUG_PRIVILEGE.

Best practice if you're working on a higher level cross platform language like Java is to leave the key management to a separate process like gpg-agent or ssh-agent. Or to a hardware security module, which does the key management, authentication, or encryption/decryption on a separate hardware. Another option is that many modern systems may also support TPM, which gives you essentially in-built HSM.

4
  • According to several sources, ssh-agent stores keys in memory unencrypted. Not sure what the benefit of using it would be.
    – bkoodaa
    Commented Jan 13, 2017 at 16:17
  • @AtteJuvonen: Running your key agent as a separate process means that any vulnerabilities in the dependant application can't be used to divulge the secret key as the dependant application and the key agent don't share memory space and the dependant application never have a copy of the secret key. For more advanced use case, you can also run your dependant application and key agent on different user account or even on a separate machine, providing further separation.
    – Lie Ryan
    Commented Jan 13, 2017 at 20:27
  • Also, ssh-agent uses mlock to ensure your keys never get paged to swap. Using mlock in VM based languages like Java is essentially impossible because the VM moves data around memory for garbage collection and other things you have little control over.
    – Lie Ryan
    Commented Jan 13, 2017 at 20:29
  • These are more effective control than encrypting your keys in memory, which is just a pointless exercise. Anyone that can dump your memory can also dump your filesystem and can just get the decryption key at the same time. Also, you will still need to decrypt the key in memory when you want to use the key, so there's still a lot of window of vulnerability. If your threat model is that the attacker that have full administrative privilege on the machine shouldn't obtain the master key, you must use an HSM, don't even bother with encrypting the key in memory.
    – Lie Ryan
    Commented Jan 13, 2017 at 20:38
4

You could use a GuardedString for the purpose of keeping password Strings a little safer. It's a special String Object crafted to deal with issues of having passwords kept in memory represented by String:

Package org.identityconnectors.common.security.GuardedString version 0.2.3. Quoting the GuardedString class file documentation:

Secure string implementation that solves the problems associated with keeping passwords as java.lang.String. That is, anything represented as a String is kept in memory as a clear text password and stays in memory at least until it is garbage collected. The GuardedString class alleviates this problem by storing the characters in memory in an encrypted form. The encryption key will be a randomly-generated key. In their serialized form, GuardedString will be encrypted using a known default key. This is to provide a minimum level of protection regardless of the transport. For communications with the Remote Connector Framework it is recommended that deployments enable SSL for true encryption. Applications may also wish to persist GuardedStrings. In the case of Identity Manager, it should convert GuardedStrings to EncryptedData so that they can be stored and managed using the Manage Encryption features of Identity Manager. Other applications may wish to serialize APIConfiguration as a whole. These applications are responsible for encrypting the APIConfiguration blob for an additional layer of security (beyond the basic default key encryption provided by GuardedString).

1
2

I believe that the ideal solution would allow you to do 3 things:

  1. Clear the sensitive data once you are done using it.
  2. Hide the sensitive data so that it is not readily visible in a memory dump.
  3. Prevent garbage collection from moving or copying the sensitive data.

Something like GuardedString, as mentioned in other answers, can give you 1 and 2 above. For most use cases, number 3 above is overkill.

However, the JVM can and will make copies of objects to and from an intermediate object during GC and other operations. So multiple copies may still be left beyond the point when you are done using the sensitive data.

To prevent your sensitive data from proliferating in the heap in this manner, you can do one of two things:

  1. Use java.nio.ByteBuffer.allocateDirect() to get an underlying data structure that is outside of the GC heap.
  2. Use sun.misc.Unsafe to manage the underlying memory allocations yourself.
0

What are good practices to reduce data lifetime of passwords and cryptographic keys in memory?

Honestly? Spend your time on something more important.

  • There is absolutely nothing useful you can do against an attacker assumed to have memory read access.
  • There is basically nothing against an attacker who can run code in the same user session even if they can't read your memory, since they can do things like log keystrokes.
  • If your users' threat environment gets anywhere near the level of "people who will go to the effort of decoding swap on a stolen laptop to try recovering secrets", then they absolutely need to be using disk encryption, which will provide far more benefit than anything you can do.

Additionally, the "decryption key on disk" thing gets you basically nothing, beyond a speed bump for the attacker. First of all, there's no such thing as using data directly from disk; you have to read it into memory first, which means it might end up in swap too. Second, it's pretty darn hard to properly purge data from disk these days, especially from Java where you don't have low-level API access; SSDs in particular make reliable overwrite (including deletion) very hard, due to their wear-leveling.

If you feel you absolutely must do something, there are some options, but Java is a bad choice of language for them. You want greater control over the location and lifetime of objects in memory, and access to platform-specific functionality, than Java is good for. Some of those options are:

  • Prevent swapping out the memory where the key is stored. This mitigates the entire "data in swap" risk unless the system is hibernated while the app is running and the disk is not encrypted, in which case there's nothing you can do anyhow.
  • Perform cryptographic operations in a hardware security module or secure enclave of some kind. The key doesn't need to be stored in system RAM, even while it's in use. Getting it into the secure environment, in a way that prevents an attacker from using it too, might not be possible, though. At best this probably only allows you to limit the windows where it needs to be in system RAM in any recoverable form, not eliminate them.
  • Disable generation of crash dumps for the process, in the unlikely event that they're enabled.
  • Check system settings, such as presence of disk encryption and kernel crash dump type, and advise the user to adopt secure ones or even enable them directly (will require elevated privileges).
  • Run with elevated privileges at all times, which prevents many otherwise-permitted forms of interaction from less-privileged processes (does nothing against other privileged processes, of course, and comes with its own hassle and risk).

You must log in to answer this question.

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