views:

409

answers:

8

I need to "password protect" my application but need advice on where to store the password securely.

How I intend to do this:

The first time the program is run, I will prompt the user to create a password. The password will be salted and hashed in SHA-256 then stored in either the Registry or a file.

The Problem:

If I store the hashed password in the registry or a file (or both) then it would be too easy for someone to just delete the Key in the Registry or the File and be prompted to create a new password...

How can I securely store the hashed password so that it makes it harder to be deleted?

I have thought about storing it in the Registry and also creating a file with the Hidden and System Attributes to read from in the event of the Registry file being deleted but this seems silly as it could also be deleted quite easy.

// I hope I have posted this question correctly with the right Tags - I am new here so please go easy! ;)

All the best

Chris (Shamballa)

+13  A: 

This is basically a Programming Ethics 101 issue. If you're storing information on someone else's computer, remember that the computer is their property and they have the right to delete or modify any file or registry key on it. Trying to make it so that they can't is a very bad idea.

There's a good reason why you can't do it. What would happen if someone started putting files that you can't delete or modify on your computer? Extrapolate to the logical conclusion: What would happen if a virus started putting files that you can't delete or modify on your computer, and did so in an infinite loop until the hard drive was full? You know if it was possible, someone would try it.

If you want a program that stores a password somewhere where the user can't modify it, put it on your server and have your program contact it over an Internet connection. (Which is an entirely different can of worms, but at least you're not trying to do impossible things or violate your users' basic property rights anymore.)

Mason Wheeler
Over the internet is a very secure way, but then you have the hassle of making sure your service is always up to allow them to login, like a few of the gaming services out there. This would also allow your licensing structure (if you have one) to be managed on your server, if the program only works when it can connect to your service. This has it's own drawbacks for not doing it.
jimplode
Yep. Like I said, this brings its own can of worms. But at least it's theoretically possible. What the OP wants simply isn't.
Mason Wheeler
I think the ethical issue cuts both ways. As long as the user can change or remove the password _by first supplying the existing password_ I don't think you're taking any rights away from them. The problem is for the user who _specifically desires_ to lock down his or her application once a password has been created — how can that be accomplished?
Larry Lustig
+3  A: 

The best solution would be to rely on an external source that the user can NOT control to store a portion of the password. Otherwise no matter where you hide it, it can easily be discovered by someone with a few free tools and a little time.

Personally, I have found the best place to store such data is in the open, along with other data that is frequently accessed by the application. Keep in mind that if the user has access to modify the data, it is at risk.

If you want to lock down your program, require that the key already exists before your program runs. This way you only have to worry about how you get them the key, and since it is encrypted it would be harder for them to create one which works for your system.

For your initial authentication process, you can place a part of the key on your webserver, give the user a passkey required to create the encrypted file. Using the pass key would lead them to the key on your server and if it is valid then allow them to save the encrypted file. If your worried about re-activation then once its activated you can delete the file on your web-server.

Another option would be to use something like OnGuard (latest versions) to encode a time-limited key that you give to the user. Then when the activation is run check to see that the key you supplied has expired or not and if so then not allow activation. This way your activation key is only at risk for a limited amount of time.

Don't spend TOO much time on this. Even the best algorithm can be patched around with a few NOP instructions after the app is deployed.

skamradt
This is a nice option, release the program with some sort of key lock. so a generated serial key will unlock the program and allow it to be used and run, then allow users to supply their own password. This is a much neater model than trying to insist they use internet connection to verify licences. Here is a link to a shareware starter kit, might give you some ideas. http://blogs.msdn.com/b/danielfe/archive/2005/07/10/437293.aspx
jimplode
@jimplode - yes that also works, but does not limit the use of the key unless there is something external to work against it.
skamradt
@skamradt: yup... licencing and serial protection is such a tricky business!! If it were me I would not bother and aim it at the professional market that would pay to use and not abuse it. Especially as they are all subject to audits they can't really cheat. The private sector.... well good luck, if it is in the hands of the general public it will be cracked no matter what you do.
jimplode
+4  A: 

You can securely store a password for an application using the Windows crypto API. There is an example of it's use in CodeGuru, but it is written in C++, not Delphi. The code is not too challenging, so should be relatively easily converted to Delphi.

A more advanced solution would be to ask the user for the password before downloading the application, and embed the hashed password part of the binary - of course if you obtained multiple copies of the application you could easily determine the location of the encrypted value, and the code checking it in order to remove it.

The issue is that you have not created any value from the use of the password, i.e. it seems to just be a password on it's own. You should use the password as a seed for encrypting the application's data, and tie the password to the data. Lose the password and you lose only the data.

Petesh
+1  A: 

There are at least 2 ways I can interpret your question.

(1) You want to store passwords so they can be used later to login to a remote database.

This answer on Password encryption in Delphi explains the encryption part.

That way you can store a password so it later can be used to authenticate the user when he logs in using your application on a database server or something.

The "not delete" part is really sensitive for users; I would not do that.

(2) You want to store a password, so it can be used to validate a user to locally access your application.

This is more difficult, as basically you can't.

The closest way is to keep a background process running that keeps a lock on the file.
You communicate with that process to unlock the file so you can verify the password.

--jeroen

Jeroen Pluimers
Sorry - SO messes up the numbering; I did type 1. and 2.
Jeroen Pluimers
...until the user uses Process Manager to detect who it is holding the lock, kills the process, and deletes the file. ;)
Mason Wheeler
That's why virus and trojan writers put so much effort in hiding their stuff. And they can't. Unless they install a root kit like Sony did for copy protection: http://en.wikipedia.org/wiki/Sony_BMG_CD_copy_protection_scandal
Jeroen Pluimers
Well (2) is what I need! I really never thought I would have so much feedback so quickly on this and am a little overwhelmed by it all. I am currently now looking into the Windows Crypto API... I won't be writing a Rootkit like Sony! ;)
Shamballa
@Shamballa: note that "Secure Local Storage" can also be detected and information from it removed. Thanks for the (2) writing hint; I changed the 1. and 2. into (1) and (2), so now the answer looks fine again.
Jeroen Pluimers
A: 

If you only need one password, encrypt and tack it on the end of the .exe. I have done this successfully many times.

Dennis
If the user is not an Administrator or does not run the exe elevated there may be no write permissions.
Remko
This sounds interesting, to store the Password inside the program? Would this not be flagged by Anti Virus programs as bad though?
Shamballa
Oops - Pressed <Enter> and it submitted before I had finished typing! I was going to add >> How did you do this? This would need to be added during run time.
Shamballa
A: 

I would suggest using the Authentification Functions in Windows, specifically CredWrite and CredRead. It would also be possible to use the encryption windows provides (CryptProtectData/CryptProtectMemory) and then save the credentials

EDIT: If you need the headers for Delphi, they are available in the Jedi Windows Api Library.

Remko
+5  A: 

You didn't really specify what this password is protecting. I'll assume it is used to protect the data created by your program.

I'm no security expert or cryptographer but if the data is stored locally the solution is simple. Store both the password(or more likely a hash of the password) and the data in the same place (file, DB, etc), encrypted with separate keys.

This prevents circumvention by file deletion. They'd delete all the data as well. This will thwart all but the most determined end user.

codeelegance
I was going to mention this as well. Use the password as an encryption key. That way, their data is really secured, and there's no point in deleting the password. The only problem though, is that at lot of people don't actually want their data encrypted. They want to be able to recover their data in case they forget their password, but they don't want their data to be easily accessible by just opening a program. I know you can't have your cake and eat it too, but that's what a lot of users want.
Kibbee
The Password is to protect access to the actual program. ie. being able to actually access the program once installed. The program I am developing is an email encryption program. It uses AES Rijndael in 256 bit CBS mode so this password is chosen just before the time of encrypting but never stored. I initialize the "key" they use with SHA-256 which becomes the actual key. It is never stored. The problem otherwise would be anyone could Decrypt data using a single pre determined key...
Shamballa
I meant CBC Mode...
Shamballa
A: 

Judging from your description, you don't understand that if all the security you have is

if not SameString(Hash(UserPassword), StoredPassword) then exit;

Then you have no security at all, and it's not a matter of user deleting your password file. User can just open your exe file in any binary editor and nop out the part which does the check:

//if not SameString(Hash(UserPassword), StoredPassword) then exit;
//Check commented out ---malicious user

You have to realize that even though you compile your app, it still contains all the source code, just in assembler. You can still edit the source, it's just a bit harder because it's in different language now.

Therefore, if you want to prevent user from doing something in your app, there are only two ways:

  1. Write-protect your app and it's files. Or store them on a separate server, if you're not in control of this one. Or just make them a service which accepts only a fixed set of commands.

  2. Make it so that app does not check it, but encrypts something critical with password. Sure, malicious user can reset password or even delete the decryption routine altogether, but he will still have to decrypt the data.

Every other solution could be circumvented, all that differs is the time and skills it'll take to circumvent. For instance, you can encrypt a critical part of application code and decrypt it on-the-fly (did that once). Then execute and encrypt back. Without the right password your app will never run.

But a malicious user can install a separate copy of the app with known password, examine parts of the program when they're decrypted and assemble them into the unencrypted source. Sure, that's a lot of work. But it can be done in a finite time.

himself