4

In my application I need to read an encrypted file that is distributed with the app. I also need to connect to a download service using a password. My conundrum is where to store the passwords for these resources? In other languages, such as C++, I would just have stored them in the code. However, as there are tools that can disassemble C#, such as JetBrains DotPeek, that is not secure.

Below are the solutions I have thought of so far, but I don't think any of them are secure:

  1. Store the passwords in the code: No good because C# can be disassembled.
  2. Store the passwords in an encrypted external resource: No good, because then you need to store the password for that!
  3. Ask the user for the password on first use (which they have been told by other means): No good, I think, because don't you still need to store it for subsequent use?
  4. Store them in a C++ dll: No good, because what is to stop anyone else calling the function in that dll?
  5. Hide and encrypt the passwords in the code: For example, don't call it password and use multiple levels of encrypting it. This would make it difficult for someone who was just text searching the code, but wouldn't stop someone prepared to debug the program to find out how the resources were accessed. No good.
  6. Obfuscate the code base to prevent disassembly: Possibly this might work. Is it secure? Does anyone do it?

What is the normal solution to this quite typical problem?

Mathieu VIALES
  • 4,526
  • 3
  • 31
  • 48
Ant Waters
  • 510
  • 1
  • 5
  • 22
  • Have a server handle the authentication yourself. This gives you full control over the resource without including the client application. – Luke Joshua Park Nov 02 '17 at 08:50
  • I thought any language could be reverse engineered ... Also, i don't think that obfuscating would help since the code will probably be compiled identically (or maybe less optimized) ... – Mathieu VIALES Nov 02 '17 at 08:55
  • 1
    I honestly think that your best bet is to ask the password from the user. – Mathieu VIALES Nov 02 '17 at 08:56
  • have you checked SecureString in c# . https://msdn.microsoft.com/en-us/library/system.security.securestring(v=vs.110).aspx – Ansil F Nov 02 '17 at 08:59
  • "I also need to connect to a download service using a password" - well ask user for that password, why do you need to store it somewhere? And "encrypted file that is distributed with the app" - you can download it too from server with that users password. – Evk Nov 02 '17 at 09:03
  • @Luke Park: I don't understand your suggestion, can you please explain. – Ant Waters Nov 02 '17 at 09:06
  • if you want to keep the password more securely, Create a cloud service and keep the password on cloud server ?(for better security use SSL for that service) – Sandeep Nov 02 '17 at 09:07
  • @Wndrr: The encrypted file is something we don't want the user to see or tamper with, so they can't know the password for that. – Ant Waters Nov 02 '17 at 09:07
  • For clarification, this app is distributed to external customers, so any use of servers would just require a password for accessing that wouldn't it? – Ant Waters Nov 02 '17 at 09:09
  • If the application needs to be able to silently decrypt the file locally then you have **no** 100% solution, it's **all** compromise. So make a spreadsheet with all the problems and all the possible solutions and tick which problem exist for each solution, then pick the solution you can live with. – Lasse V. Karlsen Nov 02 '17 at 09:10
  • @AntWaters I updated my answer regarding the new info about the encrypted file. Are there any other requirements that i missed ? – Mathieu VIALES Nov 02 '17 at 09:12
  • Who ist going to bother hacking your file? Who is gaining what discovering your passphrase? Are you securing your outgoing connention? You still could hardcode your pw in a dll, just apply some transformations beforehand that are reversable, maybe split it to different parts if youre paranoid. Use base49 encoding to avoid the overused base64. And still... If enough effort is spent, it will be crackable. PW are a deterrent. – Patrick Artner Nov 02 '17 at 09:25

2 Answers2

1

Note: if you want the authentication to be done 100% offline, there is no truly secure way since someone that has access to the computer has access to all of it content.

First off, cpp CAN be decompiled as per this SO answer. It's just ugly as hell.

Why not just use a database which would store hashed passwords ? When the user wants to read the file or download from the service, you ask him for a password then hash it and match it with the hashed version stored in your database. The matching would of course be done over a secure protocol.

Here is a tutorial about ASP.NET auth. You may read it just to understand the way they store the password and match it.

Keep in mind that obfuscation/multiple levels of encryption won't stop someone really determined.

You haven't mentioned my answer at all in your post. Do you dislike this approach or did you not think of it ?

edit: regarding the file, since the user must not be allowed to decrypt it you could have an other "key" stored in the database. When the user authenticates with their password you retrieve the key from the database and decrypt the file. this way the user never sees the key for the file.

As per Vytautas Plečkaitis's suggesstion: you could use the has of your application as an authentication token to retrieve the password for the file from the database. The idea is good from a user-friendly point of view since it allow the user to not have to give any password but it means that the "key" to the database is the same for every instance of your application (crack it once, you cracked them all). Also, this means that to obtain the key to your application all you have to do is get the hash of your executing exe ... i'm nto a security expert (not even close to that) so i dont know how secure that is but i'm not sure that it's the best idea.

To me the password/hash/database pattern is the best, especially since it has been used over and over again for years. This is the built-in method for .NET Core authentication

Mathieu VIALES
  • 4,526
  • 3
  • 31
  • 48
  • Sorry @Wndrr, my screen hadn't refreshed. Wrt your answer though, it has tow problems. Firstly, It's a pain for the user having to use a password each time they open the App. Secondly, the encrypted file is something we don't want the user to be able to see or tamper with, so I wouldn't want the password for that in a database they can read. – Ant Waters Nov 02 '17 at 09:13
  • The user can't read the database. When they enter their password, the key for the file is retrieved by your application and used to open the file. The user never sees this key and probably won't even know it exists. Now about the "pain", well you can't have it all. A truly secure system IS a pain to the users. You could have a "store password" checkbox that would store the hashed password. That's still secure and user-friendly. The system i described is the most widely used auth patter for website (at least in ASP.NET MVC/core). To me this is the most secure option you have. – Mathieu VIALES Nov 02 '17 at 09:16
  • Your idea has some merit, but how would I get the file password into the database? – Ant Waters Nov 02 '17 at 09:16
  • You need a way to "link" it with the password. I don't have enough info, it all depends on the time you generate the file at. You could ask the user for their password before generating the file, so you can authenticate to the database and insert the key for the file then. I would really need to see the bigger picture to really answer that question – Mathieu VIALES Nov 02 '17 at 09:18
  • it is a Windows Forms Desktop app. The encrypted file is downloaded periodically. – Ant Waters Nov 02 '17 at 09:21
  • Is the encrypted file is generated on the server, you can just insert the key in the database right after it was generated *for the user*. This way you can know which user has which key. – Mathieu VIALES Nov 02 '17 at 09:22
  • Thanks, there is some mileage in what you say, but I would like to wait and see if there are any other suggestions. It still sounds a bit clumsy and insecure at the moment. – Ant Waters Nov 02 '17 at 09:28
  • Or alternatively instead of password, just query service with hash of querying application (check https://stackoverflow.com/questions/8875296/how-do-i-get-the-hash-of-current-exe), and if it matches whatever you have in db - return password so app can decrypt file. No user interraction, and without unaltered exe getting password would be pretty difficult. – Vytautas Plečkaitis Nov 02 '17 at 09:35
  • Added @VytautasPlečkaitis's suggestion in my answer even tho i don't think this is the most secure way to do things. – Mathieu VIALES Nov 02 '17 at 10:21
  • It is secure. That's actually the most secure option i've seen mentioned in this thread AFAIK – Mathieu VIALES Nov 02 '17 at 10:22
  • @Wndrr - yes, it's not really the most secure way to do things, but based on hash you can determine app version (e.g. same release will always have same hash), and if it's not the newest one - you may force app to update itself and then request password from service again. Also you can salt hash, use different salts for different versions & etc - imagination is the limit. – Vytautas Plečkaitis Nov 02 '17 at 11:22
  • I agree. But i don't really get why using a database/password/hash system isn't okay for him. it's the most used method, users are used to it and it works perfectly ... – Mathieu VIALES Nov 02 '17 at 11:35
0

Did a quick search and found this gem Encrypting app.config File which could be an option for you, just store those credentials inside the app.config. What you'd be doing here is encrypting sections of your configuration file.

You cannot encrypt the entire - it's a configuration section group, which contains configuration sections.

The aspnet_regiis will only encrypt configuration sections - so you need to selectively encrypt those parts you need, like this:

cd C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727
aspnet_regiis.exe -pef "system.serviceModel/bindings" .
aspnet_regiis.exe -pef "system.serviceModel/services" .
etc.

With this, you can encrypt what you need easily - what isn't too important, can be left in clear text.

Word of warning: since it's aspnet_regiis, it expects to be dealing with a web.config file - copy your app.config to a location and call it web.config, encrypt your sections, and copy those encrypted sections back into your own app.config.

Or write your own config section encrypter/decrypter - it's really just a few lines of code! Or use mine - I wrote a small ConfigSectionCrypt utility, come grab it off my OneDrive - with full source (C# - .NET 3.5 - Visual Studio 2008). It allows you to encrypt and decrypt sections from any config file - just specify the file name on the command line.

Here is the link to the said OneDrive https://1drv.ms/u/s!AtQ29cmdYW3QgnnBpcHRRCc4_mop and it is currently active.

jegtugado
  • 5,081
  • 1
  • 12
  • 35