7

What information can be found in every C# application that can be used as a unique salt for encryption, including for web applications, windows services and wcf layers?

I would like to create a library that allows easy encryption of sensitive data stored in configuration files, using the (DPAPI) System.Security.Cryptography.ProtectedData.Protect() and System.Security.Cryptography.ProtectedData.Unprotect() methods.

The library will also be used by a separate application I'm making that can encrypt and decrypt config values outside of the applications that are using the values, allowing updates to config files without recompiling everything or needing access to the original source, although access to the source should always be available.

The salt must be simple enough to enter manually in the separate application (for instance, a GUID would be difficult to identify).

System.Reflection.Assembly.GetEntryAssembly() appears promising, if that is the assembly of the application/service invoking this library I'm making, I could use something in there. First thoughts were "make the salt the config file name the encrypted data is being stored in...", but for websites the config file is always 'web.config'.

Any other thoughts welcome.

Updates...

'GetExecutingAssembly()'... how does that differ from 'GetEntryAssembly()'?

Ninjanoel
  • 2,864
  • 4
  • 33
  • 53
  • 1
    Why the need for unique salt for each application? Or why is the name of the application not enough? – Ralf de Kleine Mar 21 '13 at 11:30
  • Application name could be suitable if its not ambiguous, when then programmer encrypts with the app name, will the support guy changing the config three years later have an unambiguous string he can identify with notepad.exe as the 'application name', that he can be sure was used by the programmer years before? – Ninjanoel Mar 21 '13 at 12:00
  • An assembly has a [Guid] attribute, look in AssemblyInfo.cs. It is unique as long as you didn't copy/paste. Using the same salt value consistently defeats the point of using salt. – Hans Passant Mar 21 '13 at 13:21
  • @HansPassant, operational staff (ie. not the devs) wont be able to view *.cs files as they wont be present in the installation directory. – Ninjanoel Mar 21 '13 at 15:01

2 Answers2

1

Every application/assembly has a version number, this could be an option.

System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();
LukeHennerley
  • 6,344
  • 1
  • 32
  • 50
  • Essentially, we have many applications, version numbers are not something we use often, we have source control that handles versioning for us. But your answer does raise the question about the difference between GetExecutingAssembly and GetEntryAssembly. – Ninjanoel Mar 21 '13 at 11:21
  • Also, essentially, this 'salt' should be easy to find with nothing more than access to the folder where the application/website/service is installed and notepad.exe. Then it can be a company wide policy of what value is routinely used for salt. – Ninjanoel Mar 21 '13 at 11:23
  • 1
    The version number will change over time, and so decryption may not be possible after an upgrade... I'm guessing that's not desirable! The simplest description of the difference between those methods is that `GetExecutingAssembly()` will give you "the assembly that the code is running from" (if you call from a .DLL, it'll give you the DLL) but `GetEntryAssembly()` will give you the "assembly that was the entrypoint to the process" (if you call from a .DLL, it'll typically give you the .EXE that it's running from, which may not even be your own code...) – Dan Puzey Mar 21 '13 at 11:27
  • @Nnoel If you are in control of all the applications, then create a custom assembly attribute that takes a Guid and read it at runtime when you need the salt. Or not even a Guid, just a jumble of text in an attribute somewhere (just Guids let you make new ones easily). – Adam Houldsworth Mar 21 '13 at 11:29
  • @AdamHouldsworth, sounds like your basically suggesting an internal value, I need a value that can be identified after the program/service/website has been installed and forgotten by the original author. – Ninjanoel Mar 21 '13 at 12:08
  • @DanPuzey thanks Dan for the distinction, but still slightly confused as to which would be the more universally consistent. I am making a DLL which will be included in WCF service layers, running from websites, from windows services, and just plain winform apps. – Ninjanoel Mar 21 '13 at 12:11
  • @Nnoel The internal value can be queried at any time by anyone, it is simply compiled into the app when the app is built. Define it once and leave it. You can then just use reflection over the DLL to look for this assembly attribute, regardless of who authored it. – Adam Houldsworth Mar 21 '13 at 14:12
  • @AdamHouldsworth this internal value can be queried? I'm not sure how I'd 'query' a value inside a dll, and as one the more experienced programmers where I work, I wouldn't expect someone else with even less experience to be able to do that without great difficulty. The value needs to be retrievable by 'lay' staff with only the use of notepad.exe and access to the installation directory. I'm setting a high standard of usuability, but what you say is probably true, but reflecting dll's etc just doesn't sound very maintainable if any other solution is possible – Ninjanoel Mar 21 '13 at 14:59
  • @Nnoel You'd query it by using reflection to search for the presence of the assembly, as I stated. Funny that you consider my approach complicated when you are considering similar code in your question. Nor do you state that a "lay" person needs to do this. If there is a convention to use some property of the application to gain the salt, there is no more complexity by stating the convention is some meta-data of the DLL. Encryption & configuration tends not to be the domain of "lay" people. Good luck. – Adam Houldsworth Mar 21 '13 at 15:08
  • @AdamHouldsworth I have considered that perhaps my 3rd application that will be encrypting and decrypting could be pointed at the dll in question (and then check the assembly info?), but sometimes its a exe, sometimes a website? I say 'lay person' because I'll trying to make it simple, simple means in years to come it will still be understandable and thus maintainable. – Ninjanoel Mar 21 '13 at 15:17
  • @Nnoel Even more simple would be to just have a configuration item for the salt and leave it at that. Conventions get lost to time, company policy changes. Fact is that once it's defined I would put money on it never changing. The encryption source and the decryption source both need the same salt so a config is a good choice, no real reason for it to be per-application. Config files can be opened in notepad, and the user can type whatever they want, so long as it's the same on both sides. – Adam Houldsworth Mar 21 '13 at 15:19
0

System.Reflection.Assembly.GetEntryAssembly().GetName().Name...

appears to be the name of the exe or DLL, or more precisely, VS2010 uses the Assembly name as the name for the exe. I'll need to investigate how this works with websites and services.

If my external application that encrypts and decrypts the config values (encrypting app) can also 'peek' at a requested assembly's 'name' (the program using the encrypted config), then any applications using the encrypting library just uses the library without providing salt, and the library can work out the assembly name for itself (of who is calling it) and use that as salt. If a dll or exe gets renamed I have a mechanism to retrieve the assembly name value, built into the encrypting app.

p.s. I'd prefer not to mark my own answer as 'accepted', so refine my suggestion and put it into you own answer and I'll promise to mark one of those as 'accepted' if I get any good ones.

Ninjanoel
  • 2,864
  • 4
  • 33
  • 53