1

My current application has a need to encrypt and store sensitive data and then decrypt it again for use at runtime. It's C#, but this question is language independent.

I've built myself a cipher class which uses the Rijndael algorithm and a randomly-generated salt to encrypt and decrypt a piece of data against a passphrase. Should be secure, so long as an attacker doesn't get the passphrase.

So the question is: is there any harm in hard-coding the passphrase into my class? We'll assume an attacker can't get the source code but, if they've got the data, they can likely get the compiled code too since they could be on the same server.

  • Is it an application that the client install or is it a server that the client access, let's say, with a webbrowser? – Gudradain Feb 7 '17 at 14:20
  • @Gudradain Neither: it's a windows service which needs to store logon credentials to external web services in order to do its job. – Bob Tway Feb 7 '17 at 14:21
  • External web services = service on other computer right? I'm asking because if your code is only installed on your server there are means to protect this passphrase, for example with a config file outside the source code, but if your code is install on the client computer you can't protect it and you need to look at other scheme. – Gudradain Feb 7 '17 at 14:22
  • 2
    @MattThrower it sounds like you may be suffering from an X/Y Problem and that by withholding information to "keep the explanation simple" you are stopping us from determining the best solution to the actual problem. – Trotski94 Feb 7 '17 at 15:23
  • 1
    1) you give customers the software. 2) the key is in the software. 1+2 = you give customers the key. As simple as that! It's like house keys hidden under a rock in the garden - it's only good until someone thinks about possibility that they keys are there. – Agent_L Feb 7 '17 at 15:33
14

No, it's not secure.

Any compiled application can be disassembled and examined. The CIL bytecode generated by your C# compiler can be traced instruction by instruction just like any other programming language. When you hardcode your cryptographic key, it will appear somewhere in the assembly. (the same applies to machine code generated by "real" compilers, by the way). It's not if someone will find your key, the question is when.

You could encode your key, but the encoding algorithm must also be part of your assembly, so it can be found and used by the attacker.

You could use some code obfuscator which makes the assembly less readable, but that usually affects performance negatively and is also just an additional obstacle which will cost the attacker more time but will not prevent them from finding it when they are diligent enough.

  • So ... what's the solution then? Store the password in a config file and use it to encrypt itself? – Bob Tway Feb 7 '17 at 14:19
  • 1
    @MattThrower If you encrypt the password in the config file with itself, how is the application supposed to decrypt it? What you are trying to do is futile. When the application is supposed to use the password, it needs to know it. When the application knows the password, an attacker can extract it. – Philipp Feb 7 '17 at 14:22
  • Note that you might not even need a disassembler to read the password. If it's declared as a string in the code, all an attacker needs is a hex viewer. – dr01 Feb 7 '17 at 15:19
  • Or not even that, if the key is not random, but contains human readable characters: On linux, there's a command "strings" which searches for anything that looks remotely like a legible string in binary files. – Out of Band Feb 7 '17 at 16:01
  • Since C# was mentioned in the question, I want to add a thing on decompiling: It becomes very evident if you try one of the many freely available .net assembly decompilers like ILSpy (ilspy.net) or dotPeek (jetbrains.com/decompiler) on your own assemblies. You'll see just how easy it is to reconstruct the actual source. Obfuscation, as already mentioned, would add an obstacle, but it is surely nothing you should rely on. I encourage anyone who works with .net languages to use those tools and be aware of the problems that come with intermediate language (IL). – knipp Feb 7 '17 at 18:07
6

To add to Philipp's answer:

It's neither secure, nor can it be made secure, no matter how much effort you put into it.

But you can make it easier to deal with problems. If you store the key in an external file instead of somewhere in the code of your program, it's much easier to change. So while you can't protect the key from being stolen and the data from being decrypted, you can make it easier to regularly change the key, so that an attacker must periodically regain access to the key if he wants to keep reading the encrypted data. This increases the chances of being detected (he might trip over some kind of intrusion detection system sooner or later, or make a stupid mistake)

Separating key and application also makes it easier to protect the key - now you only have to protect a small file and don't have to worry about where the application binary and source code might be stored (think version control systems, package managers, automated build environments, backups etc).

Keeping the key in an external file is also a good idea because depending on which platform you're running on, your application can start with elevated permissions that allows it to read the key, and then drop these permissions so that while it's running, it won't have access to the stored key any more. This will prevent a few types of attacks, even though a sophisticated attacker can of course always pull the key from the application's memory.

Depending on what your application does, it might also be possible to reduce the attack surface significantly. If one part of the application only ever writes secret data, you can split your application into two parts and use public key cryptography to stop having to worry about the first application, the one which only needs to write data, but not read it back. In that case, you give the first application a public key to encrypt a session key with, which you use to write the secret data. Now you only have to protect the second application, which reads the data back, or rather, the private key this application has access to.

2

As the other answers explained, your approach is insecure. However, to add to the other answers, there is a concept which attempts to solve a similar problem (at least from a practical point of view; principally, if the secret is in possession of the attacker, however obfuscated, you must consider it freely usable by the attacker), which is called white-box cryptography. See e.g. this question and whiteboxcrypto.com:

The challenge that white-box cryptography aims to address is to implement a cryptographic algorithm in software in such a way that cryptographic assets remain secure even when subject to white-box attacks.

The point is that you cannot use “classic” concepts and methods, e.g. “hard-coding the passphrase into my class” as you write. You’d need to “bake-in” the encryption algorithm and the key into one “obfuscated” transformation.

1

No it's not secure and you need to change your architecture if you want to secure it.

Your current architecture

Client application < -- > Web services

To communicate with the web services you need a secret password that the user is not supposed to know. But since the client application is installed on the user computer, there is no way to protect that password as the other answers have mentioned.

Now to protect, these passwords you need to change your architecture.

A new architecture

Client application < -- > Intermediate Server < -- > Web services

Now you can safely store the web services passwords on the intermediate server. Usually, you do so using a config file external to your source code for the intermediate server.

And...

Now, the question is how you protect the access to the intermediate server? But that should probably be another question.

  • This is the equivalent of having a local password encrypted with another local password. – Dmitry Grigoryev Feb 7 '17 at 15:35
  • @DmitryGrigoryev ?? This is a pretty common practice to protect the password of web service. It has the advantage that you can limit the access to the API you want to protect. For example, a database is usually a web service (even if we forget that fact). Do you give the password of your database user to your application user or do you use an intermediate server to protect the database credentials? – Gudradain Feb 7 '17 at 16:11
  • But I still give away the password to the intermediate server, right? – Dmitry Grigoryev Feb 7 '17 at 16:19
  • @DmitryGrigoryev Which password? If you mean the password of the web services then yes the intermediate server will know it, but the intermediate server is something that you control and run on your machine contrary to the client application that run on the user computer. Hence, you effectively protect the web service password. Now, if you want to protect access to the intermediate server that's another question and you can introduce separate username password for each user for example. – Gudradain Feb 7 '17 at 16:37
  • No, I meant the password which the application uses to access the intermediate server. – Dmitry Grigoryev Feb 7 '17 at 16:50

Not the answer you're looking for? Browse other questions tagged or ask your own question.