1

I have an application that handles encrypted data and I have tried to be as careful as possible to make the keys inaccessible, but of course the application needs to know them somehow.

I have hardcoded the keys as function return values so they should never hang around in memory too long, however I guess it is still possible for them to be read. Is there a way to make a region of memory inaccessible? I am not a computer scientist so apologies if this is a well-known problem (I suspect it is).

Protecting them from a decompiler is a question for another day...

Thanks in advance!

Matt Wilko
  • 26,994
  • 10
  • 93
  • 143
Johnboydump
  • 21
  • 1
  • 2
  • hey mate, welcome to stack overflow, here is a thread that I found that you may find useful, http://stackoverflow.com/questions/23513831/hash-with-md5-in-vb-net – user1234433222 Jul 26 '16 at 07:03

2 Answers2

1

The way to do this is to use a SecureString. It is a bit more awkward to use than a normal string but it is the exact thing you need for this scenario.

Here is the docs to it: https://msdn.microsoft.com/en-us/library/system.security.securestring(v=vs.110).aspx

and some more information here about it: Is SecureString ever practical in a C# application?

Here is an example of setting this to use a 'String value'

        var s = new System.Security.SecureString();           
        s.AppendChar('s');
        s.AppendChar('e');
        s.AppendChar('c');
        s.AppendChar('r');
        s.AppendChar('e');
        s.AppendChar('t');
        s.AppendChar('s');
        s.AppendChar('q');
        s.AppendChar('u');
        s.AppendChar('i');
        s.AppendChar('r');
        s.AppendChar('r');
        s.AppendChar('e');
        s.AppendChar('l');
        s.MakeReadOnly();
Community
  • 1
  • 1
Matt Wilko
  • 26,994
  • 10
  • 93
  • 143
  • 1
    You can't hard-code a SecureString, and it's intended for strings (if anything). DPAPI is much more applicable for a key (binary data), but still can't be (meaningfully) hard-coded. And memory protection schemes are very weak, security-wise. – bartonjs Jul 27 '16 at 16:40
1

Edit: Added a case where an HSM isn't necessarily the solution

As you mentioned, a decompiler can get at your keys; that's part of the reason that you should NEVER have a decryption key hard-coded (a hard-coded public key to encrypt for is less bad).

If I mis-understood the question and your key isn't hard-coded but you're trying to hide the key when it isn't needed then an API like ProtectedData.Protect may what you are looking for.

But depending on what you're doing, that may not be the right answer (who is your attacker? what are you defending from?).

Defending from:

  • A Watson dump that gets sent to Microsoft containing the key
    • ProtectedData.Protect (or HSM)
  • An arbitrary-memory-read security vulnerability in your code being exploited by a remote attacker
    • ProtectedData.Protect (or the sarcastic "don't write that kind of vulnerability", or HSM)
  • An administrator (legit or otherwise) being able to attach a debugger and read the key
    • Move the key to a Hardware Security Module (HSM)
  • Your process being paged out and an administrator being able to read it from the pagefile
    • HSM
  • An arbitrary-execute security vulnerability in your code being exploited by a remote attacker
    • HSM
  • Your system hibernating and the hibernation payload being read by someone who steals your hard drive
    • BitLocker or HSM
  • A process crash dump that is still on the hard drive and the drive gets stolen
    • BitLocker or HSM
  • The entire computer gets physically stolen
    • BitLocker (but not necessarily an HSM, since that would have been stolen, too).

You'll note that the list of things that you can actually defend against with memory protection is small. Much better is making it so that nothing can ever read the key, by moving it to an HSM. Windows CNG supports symmetric encryption via an HSM, and .NET 4.6.2 (currently in preview) supports utilizing this behavior with the AesCng(string, CngProvider) constructor.

bartonjs
  • 30,352
  • 2
  • 71
  • 111
  • The "NEVER have a decryption key hard-coded " is later predicated by: "who is your attacker". "NEVER" is a little harsh, the information may be trivial (where is the beer bash), the attacker might an average curious teen. It is not trivial to disassemble the file and she is a professional security person. In some instances the fie is encrypted and decryption even is not directly possible, only activity debugging with the devices passcode and a rooted device. Finally, no scheme is 100% secure. – zaph Jul 27 '16 at 19:35
  • As for the HSM, that is a great solution but there are caveats: one must have access to the server be able to install one, typical HSMs start around $10K, generally the key is still going to be in RAM when used. – zaph Jul 27 '16 at 19:39
  • 1
    @zaph True, "never" may not be applicable, but there's a question of "if you don't care that someone broke this key, why was it encrypted?". As for the HSM, the point was that a proper threat model has to be determined, and an HSM solves many (but not all) threats (and not always the easiest/cheapest). But a proper HSM would do on-chip encryption/decryption, so the key shouldn't be in the main computer's RAM (which is why it's effective). – bartonjs Jul 27 '16 at 22:01
  • It is not "if you don't care that someone broke this key, why was it encrypted?" But is the attacker defined by the threat model defeated, if so the encryption is sufficient. Not all encryption is done in HSMs, a DB will get the key from the HSM and use it in RAM for encryption/decryption of entries. If encrypting many gigabyte files that is most likely not going to be done by an HSM, only the key will be protected. The point: It is not so black and white. As you state there needs to be a threat model defined and that model met if possible. – zaph Jul 27 '16 at 23:44