i am starting to use cryptostream class. i may be wrong, if you encrypt something, close the app, and then try to decrypt it, it will not be able to because a different key will be generated. because i do need this functionality, i am wondering if it's possible to save the key in application settings and whether this is the right way to go?
If you always run your app under the same user account (it can be a local user or a domain user), the best option would be to use DPAPI. The advantage of using DPAPI is that you do not have to worry about the key (the system generates it for you). If you run the app under different user identities, then it gets more complex because the options that are available range from bad to worse (the major problem is: how do you protect your secret: key, password, passphrase, etc). Depending on what you want to do, you may not need to use encryption at all (e.g. if you want to encrypt a connection string, consider using integrated windows authentication, which does not require a password). For more info on the topic, check out this MSDN article: Safeguard Database Connection Strings and Other Sensitive Settings in Your Code; it may give you some ideas.
Lots of applications save the keys in configuration files. It's a common bad practice.
It's not secure but all secure options are hard to implement. There are options using different factors,
You can derive the key from a password using PBE (password-based encryption). But you have to enter a password to start your application. This is so called "What you know" factor.
Put the key in a smartcard. This is very secure but you need to have access to the card on the machine. This is called "What you have".
Ignore other schemes involving encrypting keys with yet another key. It doesn't really change the security strength.
Related
Let's say I have a program written in VB.Net with encryption code that relies on a key being set to encrypt and decrypt. How do I securely store the key in the program? If it's plain text in the code, it could be reverse engineered. If it's a setting, then it is stored as plain text in the x.exe.config file and even easier to find.
Can the x.exe.config file be set to encypt? If not, what's the safest way of hard coding the key into the program?
The method I've used is encrypted using a different method, then encode that (as it's non-ascii text) and store that in the settings, but that in turn could be decoded if the program is reverse engineered.
What do other people do in this situation?
You've set to an impossible task. The problem is that by hardcoding the key into the program, as you've noted, the user can still get the key by reverse engineering. If you put it in a file somewhere, the program needs to be able to read it, and therefore the user can also access it in the same way.
The fundamental problem you have is that the software needs to access the key, and for that, the key must be stored somewhere it's reachable by the user too. It can be within the binary or in the computer, but the binary can be analyzed and the file system can be inspected. Encrypting a file protects the key, but just recreates the problem with the new key.
This is also the very same problem that all DRM schemes face. They give users access to the the full software but want to limit it in some ways, but the user has everything in his computer to run the software. That's why it's always possible to pirate every desktop software, if enough effort is put towards it. You only can make it more difficult by obfuscating the key.
But what can you do then?
An alternative approach is to not have the user to have the DB credentials at all. Or make them useless for anything significant. I can think of two approaches here:
Have the system communicate with a webservice and never to the DB directly. This way, the user only knows the address of the server and the WS can request any authentication as needed, before going to the DB. The WS is then the only one to ever touch the DB. This is what all websites do in practice, the visitor doesn't ever sees the DB, but interacts with it though the web server.
Another option would be to give the user direct DB access, but those credentials only give permission to call some stored procedures (or access views without sensitive data) and those in turn request some sort of authentication before proceeding. This way the DB credential becomes not that sensitive as long as its permissions are kept to the bare minimum and privileged actions are properly validated before proceeding.
I would like to encrypt some of my Windows 8 app data (stored in local storage folder). This is not very sensitive data, however I would like to prevent users from forging/modifying it (and was looking into encryption as a way to achieve that).
Is there any secure key store available that I could use to save my key for later reuse? What I would like to do is:
1) on the first run generate the key and store it somewhere,
2) encrypt the data using the key,
3) anytime i need to decrypt the data i would retrieve the key from the store.
Did you have a look at the PasswordVault class yet? http://msdn.microsoft.com/en-us/library/windows/apps/windows.security.credentials.passwordvault.aspx
Basically all confidential information should go in there.
If you want to 'prevent users from forging/modifying it', the question is, how much energy you are willing to put into this.
Generally speaking, data in the PasswordVault should be secure without using additional encryption. Regarding security above that level it can be said that an attacker with physical access to the computer can do anything with it, as you'd have to store the keys on the same machine. Anything more swiftly reaches a point of diminishing returns against invested effort - i.e. just adding some obscurity instead of real security.
Be careful with the PasswordVault solution, I discovered that it is actually a problem because it is a roaming settings. If you open your application on two devices at the same time, you will get two encryptions keys, but after a day or so, the roaming setting will override the first generated encryption key.
What algorithm should I use for encrypting and embedding a password for an application?
It obviously is not bullet proof, but it should be good enough to thwart someone scanning the database with a hex editor, or make it hard for someone who has the skills to use a debugger to trace the code to work out, either by scanning for the encrypted password, or using a debugger to run through the decryption code.
Object Pascal would be nice.
Major Edit
I think I did not explain myself well enough. The password needs to be decrypted back into its original form and applied. The application itself uses a local SQL database and a local webserver, and the password is fixed and can't be changed by the end users. It is to ensure that changes to be made only from within the app itself. The user passwords are only to allow access to the app itself, rather than the database
/vfclists
If you want an easy solution just stick with a good hashing algorithm like MD5 and store just the hash inside your application. Then whenever the user inserts the password you will calculate the hash of the password and check if it's equal to the one stored.
Of course this approach is a simple solution that doesn't allow you to retrieve the password if it's lost but it should work quite fine if you just need some protection..
EDIT: I mentioned MD5 that was fair good but not anymore, of course you can choose any other stronger function like SHA-2 (512/384) that is more robust. I just wanted to explain an approach more than using a specific hashing algorithm.
SHA should be ok for you, best with salt.
I don't know Object Pascal very well, but probably this will help you:
http://sourceforge.net/projects/op-crypt/
When an application has to do password checking only, it is best to save a hash. An hash can not be decrypted, but it can be checked whether the password the user enters has the same hash.
If you want to save the password so that it can be recovered, it is best to encrypt it first, using some crypto library.
I would suggest SHA1, its one way encryption, i've used it before and by far no one has decrypted it!
If you need more information on sha1 visit http://en.wikipedia.org/wiki/Secure_Hash_Algorithm and http://www.openssl.org/docs/crypto/sha.html.
PS: If you're using php you can simply encrypt with SHA1 using the sha1(); function!
I suspect that what you're aiming for is not storing passwords in the application, but trying to prevent the application itself from being run without the password, as a form of DRM. If that's the case, and you're looking to stymie people with debuggers, I think you're well into the realm of needing either a hardware dongle, or a network-based lock. Off the top of my head, I know SafeNet carry products that do this (and I've had some exposure to them in the past, they seem decent), but I don't know how well they compare to the rest of the market.
If you want as much real security as is possible in the scenario you're describing, you should require that when the system is installed an "administrator" enters the database password and his own administrator password; the application should then store a salted hash of the administrator's password, and it should store the database password encrypted with a differently-salted hash of the administrator's password. The database password (or information sufficient to reconstruct it) will be kept in memory while the program is running, but absent the administrator password there would be no way to retrieve when the program isn't running, even with full knowledge of the system.
If it's necessary to allow multiple users to access the database, an "add user" button could allow the addition of a user account. When the user types his password, use it to store hashed/encrypted data as with the administrator.
Any user with a debugger would be able to leverage his knowledge of a valid user account and password into knowledge of the database password, but someone who didn't have knowledge of a valid account password wouldn't be able to do anything.
If I am interpreting your question right, then you want to basically distribute your application to users, allow them to run it, and have the application update your database. At the same time, you want to prevent that person from being able to log in to the database and use it themselves directly.
If your program can be decompiled (like java, but I don't know about other languages like C, C++), then the person who has your application will be able to see the source code. Once they have that, there will most certainly be some way they can discover the user name and password. Even if your source code has stored the password using a reversible encryption algorithm, the person who holds your source code will be able to write similar code as yours to reverse the encryption and discover the password.
Even if your application cannot be decompiled, the user may be able to capture the network packets it sends to the database and determine the password from that. I don't know if you can communicate with the database over SSL.
Instead, I believe you need to split your application into client and server applications. You can write a restful web application, or use a messaging service (like JMS for example), and write a client application that uses it.
In that case, you may or may not want to have user accounts that are managed by your server side application. Let me be clear here, I am not talking about database accounts, but accounts that your application manages, and whose details happen to be stored in the database. If you do create user accounts, you can follow the pattern in my original answer shown below.
============== Hashing Approach, my original answer ============
As others have already mentioned, it's best to add salt to the password and use a digest algorithm before you store the password in your database. However, I think a little more detail is in order.
Using SHA1 or SHA2 with a salt value may be pretty strong, but there are even stronger methods. I highly recommend that you read this section of the spring security manual. I don't think you are using spring or java, but that section covers the concepts involved very well. Allow me to paraphrase:
Use at least an 8 byte salt value, up to 16 bytes would be great. The salt value should be different for every account, if it is the same then a cracker will only need to produce one rainbow table! It should be randomly generated. The documentation doesn't say this, but I also recommend using a secure random number generator, don't use a random number seed that produces a consistent sequence of numbers.
You should hash the password multiple times because it will cause brute force password hacking attempts to take increasingly more time. Indeed, you may want a slow password encoding algorithm instead of a fast one.
Store the raw salt value in the database along with the password, you can even store it in the same field/column. This is required so passwords can be verified in the future.
The BCryptPasswordEncoder is a good example of this.
===============
One alternative approach that may or may not solve your problem is to create a database account that has limited privileges. For example, you could create a database account that can only select, update, insert, and delete on specific tables in your database. You may not find this acceptable, because you may not want to let people do those operations directly, while you may want to let the application do those operations. It depends on your specific situation.
One of the goals of OpenID is to be resistant against the failure of any one corporation. This sounds good, but there is another problem: if the site your ID is hosted on goes down, so does your ID. I thought that there must be a login system that would be totally resistant to failure.
My idea is like this: I go to a website and I have to login. I give them my public key. The website sends me back some random data. I sign this data with my private key and send it back to them. If the signature is valid, I get logged in. This has the advantage that my ID is just my public key, so I don't rely on any external site.
To make it so that users don't have to remember there keys, the system could also optionally allow an OpenID-like system where my keys are hosted on some server and the original site redirects me there to login, and that site signs the data and sends it back to the original site, and I am logged in. This method would work similar to OpenID, but would allow me to back up my keys so if that site goes down, I can use another site.
Is this a practical system? Am I just wasting my time? Should I not reinvent the wheel and just use OpenID?
Identity cards, like Windows Cardspace, are a good alternative because they are stored on your computer and can be backed up. This is technically called the Identity Metasystem or Identity Cards.
This is different from a centralized identity service like OpenID. The good thing about the OpenID system is that the chance of everyone's identity server of going down is pretty small. However, individually, each user can possibly experience an outage.
The InfoCard system by Microsoft is a good solution, although it has not been very popular.
This is not a new problem-- email signing and encryption is a similar solution to private/public key system. GPG actually does have keystores where you can post your public keys so that people can verify your signatures.
If you're really wanting to avoid any possibility of an identity server being down(a pretty strict requirement), use CardSpace, or some other private/public key system where the users themselves have the keys, and only have to demonstrate that they have them by some challenge-response hashing algorithm.
Also, the cardspace solution is not strictly a Microsoft thing, there are plenty of applications for all operating systems. I believe it is a public standard.
This is very similar to how HTTPS works.
With your idea, you need to take good care of your private key. What if your comnputer crashes, etc. Also what about logging in from someone eleses computer? Would you trust putting a thumb drive with your private key on it into someone elses computer?
This is also very similar to what the military does with ID cards with private keys embeded on a chip that they issue to service members. A member needs to put his ID into a special reader as well as logon with a unique ID and password that must be changed periodically. This is to take care of the case where a member looses his ID and someone else trys to use it.
So I guess my answer is yes, you have a good idea, but perhaps you just need to refine it some more.
Use OpenID. It's so easy to set up and you don't have to debug it.
Windows CardSpace supports something like this. But it hasn't really taken off.
The problem with your system is that if you lose your key due to hardware problems or a system crash, you lose your only way to get to the sites you use that key for.
I would say OpenID is sufficient.
I see a couple issues with your system
I need to have that key to login. If I go out, and don't have the file on my person or hosted remotely, I'm out of luck. I also may not be able to enter it on my cell phone or some other device.
You will also need to protect the key from loss. Which likely means password protecting the key, which takes away alot of the convenience of the system.
What needs to happen for OpenID to be more resistant to ID provider failure, is for sites to allow multiple OpenIDs to be associated with an account, just like SO does. So, your idea may end being workable, but I think the effort to get it working and adopted would be much greater than the work to get widespread adoption of sites allowing multiple OpenIDs.
Also, check this link for a description of TLS Client Authentication
Right now I'm building a personal site/blog and have pretty much got it they way I want except I'm in two minds about how to add posts to it.
It's just me who'll be adding posts and to me having a user / name password to log in seems rather passé ;).
I'm looking in to alternatives to play around and experiment with and one idea I have is this:
Generate an asymmetric key, I personally keep the private and the site has the public key. When I try to add a post or modify any content the site will generate a random string, encrypt it with the public key and display it. I decrypt this using a little app I could whip together and pass the unencrypted string back to the site which will allow the modification to continue.
I'm just wondering about any caveats I should be on the look out for, or if anyone thinks this is a bad idea, perhaps an alternative I could try?
Why not just have a user name and password and either have your web browser remember the login, or send an authentication cookie back that doesn't expire. Use a self signed SSL cert to secure the communications channel. If you want to use public/private key crypto just setup an SSH tunnel and post from localhost on your server. Trust me, it's better to re-use known good crypto/security than to try to roll your own.
Why not go one stage further from your suggestion and put the encrypted string in to the URL?
For example, turn the current date and time into a string - eg. 0904240905 - encrypt it with your private key and add this to a URL, e.g. http://yoursite.com/admin/dksjfh4d392s where dksjfh4d392s is the encrypted string. You site then has a servlet which extracts the encrypted string from the URL, verifies that it decrypts to a recent time and then gives you a session cookie while allows you to perform admin tasks.
I think the asymmetric key is an elegant solution - but a username/password is almost certainly going to be easier to implement.
If you're building your own site then you are just doing it for kicks (otherwise you'd be using WordPress, Drupal, Django, etc.) so why not do things differently?
You might find that having to carry around your keymat app might get a little restrictive, if you find yourself wanting to blog but without the means to identify yourself.
But, that said, #Kurt has the right idea for crypto - DIY is almost certainly going to be worse than using something already tried and tested.
One of the wisest statements I ever heard about security was "don't try and re-invent it".
Online security has been through so many iterations that it's highly likely that any bright idea you come up with has some flaw that has previously been found, considered and fixed.
If you want "casual" security, secure your site with a user name and password. If you want "strong" security, stick an SSL certificate on top of it. If you want "bank" security, add in anti-keystroke security.
SSL client certificates do this anyway. Why not just use one of those?
The main reason more people don't use SSL client certificates is that they're an administrative nightmare - you have to get end-users to create keys, then sign their certificates, then make sure the end-users don't lose their keys (when they lose their laptop, upgrade to a new OS etc), which they usually do, so you have to sign YET MORE certificates when the end-users lose their private keys.