3

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?

Atte Juvonen
  • 440
  • 1
  • 4
  • 10

3 Answers3

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.

Sjoerd
  • 28,897
  • 12
  • 76
  • 102
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.

Lie Ryan
  • 31,279
  • 6
  • 69
  • 93
  • According to several sources, ssh-agent stores keys in memory unencrypted. Not sure what the benefit of using it would be. – Atte Juvonen Jan 13 '17 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 Jan 13 '17 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 Jan 13 '17 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 Jan 13 '17 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).