I'm creating some encryption in my asp.net webform, using the AES and the built in RijndaelManaged.
I'm wondering what kind of key system I should use. I want the SSN to be encrypted in the database, and to only be decryptable by either the owner of the ssn, or an authorized admin.
What I'm wondering is, if the encryption key is created during the application, then won't I no longer be able to use it once the application is closed? Would I have to store the key in the database? That seems to ruin the point of the encryption. Is there a way to get the same key every time based on perhaps a seed number? Probably not, that seems like it would make it very easy to crack. How do I approach this problem?
In the end, the web application has to be able to read the data and present it to authorized users. If you want more than a single user to access the data, then you need some way to get at the data with a method that is not unique to a specific user. This means having to trust the app to give it to the right person.
What this means is that you should likely just encrypt the value in the database using database level encryption, assuming you're using a database that offers this. Then your app can determine whether or not to show the data to someone, based on whatever authorization mechanism you have in place.
Well, with encryption you will always end up with this problem - what to do with the keys? Key storage and management is its own field.
Some approaches for you to evaluate:
Use DPAPI to encrypt. With DPAPI Windows handles key storage under the credentials of the user your ASP.NET app runs as.
If you are authenticating the user yourself using some secret (a password), you can derive the key from the password and a salt. Remember to re-encrypt the data if the user changes his password! The salt can be stored in cleartext alongside user information. You can derive a cryptographic key from a password doing something like this:
public static KeyIV GetKeyBytesFromPassword(string password, byte[] salt) {
using (var aes = new AesCryptoServiceProvider()) {
using (var deriveBytes = new Rfc2898DeriveBytes(password, salt)) {
var res = new KeyIV {
Key = deriveBytes.GetBytes(aes.KeySize / 8),
IV = deriveBytes.GetBytes(aes.BlockSize / 8)
};
return res;
}
}
}
If you really need top-notch security you can use a Hardware Security Module (HSM), which can be an independent piece of hardware (see for example Thales) or a board for your computer (see for example the IBM 4764 PCI-X Cryptographic Coprocessor or similar). In this case you are using specialized tamper proof hardware which will handle key storage and management for you.
Some database products have what is called Transparent Data Encryption which basically will encrypt a whole database table for you transparently. It's very expensive though. Oracle and SQL Server both have it.
lot has been discussed here: What is the best way to encrypt SSNs in SQL Server 2008? .. I have encrypted password using RinadaelManaged and stored Key and IV along with encrypted password for description. The key and IV is different for every record.
http://msdn.microsoft.com/en-us/library/system.security.cryptography.rijndaelmanaged.aspx
Related
I'm developing a desktop application in C#. In my application user should login before using my application. Now I want to save my username and password securely.
I know about hashing my username\password and adding salt to my password and saving hashed data in a file; but in this case user can replace this file with previous one. And I know we can't prevent this completely but I want make it hard.
One solution is storing hash of file in registry to prevent changing this file; but I think there should be a better solution.
Edit: I don't use database and I'm using windows 7.
You can follow this tutorial: http://msdn.microsoft.com/en-us/library/aa302402.aspx
It uses CryptProtectDataAPI, that provides the following:
The CryptProtectData function performs encryption on the data in a DATA_BLOB structure. Typically, only a user with the same logon credential as the user who encrypted the data can decrypt the data. In addition, the encryption and decryption usually must be done on the same computer.
Check more info here: http://msdn.microsoft.com/en-us/library/windows/desktop/aa380261(v=vs.85).aspx
I'm very new to the topic of encryption.
I'm building a WPF application (to manage database permissions) with a config file that contains one connection string that needs to be encrypted. I'm using 256 Rijndael encryption and generate a symmetric Key and IV.
Now that I have the Key and IV I can generate the proper Rijndael key to decrypt the relevant XML node. What I need now is a readable password that each authorized user receives from me in order for the app to successfully talk to the db. It's ok if the user has to type the password in every time the app is launched.
Am I approaching this correctly? Is there an easier way to do what I'm trying to do?
Would really appreciate the help.
thanks!
I am doing an AES encryption in my C# code, using a key which is generated using PasswordDerivedKey function by passing a password and a salt of 12 byte. I have implemented the logic in my application code and the "password" is the username of the logged in user and the salt is a static byte aray.
What is the best way of storing the password and the salt, as someone can easliy determine the salt (by reflecting my code) and the username of a person.
What are the alternatives I can adopt to store the password and the salt in a secure way. I dont think storing them in my application code is the best way of doing it.
Edit: By password, i meant the passkey used in the PBKDF function (to derive an encryption key) and its not the password provided by the user. I am using Windows Authentication
Why would you need to store password if it is merely an encrypted version of the windows username?
Anytime you need to encrypt/decrypt you know name of user thus can generate key dynamically.
Salt should never be considered a secure asset. No need to hide it. You should always assume attacker knows the salt. Salt is simply a mechanism to defeat rainbow tables and other fast lookups.
Is there something I am not seeing?
On Edit
The issue is misstated in the question. The issue isn't what/how should be stored. That answer is simple. Never store any of the cryptographic data (except salt).
The current implementation creates an encryption key from the username of logged in user. The problem is that is insecure as determining username is rather easy. To get around this one would need to either:
a) accept the implementation is insecure to someone willing to decompile app.
b) ... not a good idea ... hash can change based on groups/roles
c) use a unique secret password for each user.
c is the only secure implementation however it requires prompting the user for a passphrase when encrypting or decrypting.
Against whom must be the data be secure? If the currently logged in user is allowed access to the data, but other Windows Authentication users are not allowed access, what you really want is for the data to be encrypted for the particular logged in user. If you have access rights to configure the PC, you might be able to create an Encrypted folder with permissions only for the desired user. This is not 100% secure (you can still intercept the data at various places if you have root access), but your only other reasonable alternative is to add another password.
Alternately, you can simply accept that the protection is weak and provide minimal obfuscation. It depends on the value of the data and the capabilities of your possible attackers. If your attackers have sufficient privileges to Reflect over your assembly on the actual machine, then it's highly likely that they're also Administrator, which means you're pretty much screwed no matter what you do. There are tools that can connect to a running process and monitor its memory, which means they could simply wait until you've decrypted the data and read it from memory.
Best way to keep the salt is to generate it on runtime and keep it per session along with other user stuff such as username and password:
use signs in and provide username/password
hash with stored salt and check against password hash
create new salt and store it along with the hash
Symmetric encryption (or even asymmetric) is not at all recommended for passwords. You not to hash it which is just one-way.
I added this as an second answer because it is a different solution. I just thought of it tonight because I am working with this class (trying to reverse engineer kindle encryption).
You may want to look into the Protected Data Class
http://msdn.microsoft.com/en-us/library/2c64xe0y(v=VS.90).aspx
This is a class that allows you to store data in the windows cryptographic store.
By using the Protect and Unprotect function you can pass data into and pull data from the cryptographic store.
If you didn't want to force the user to create (and remember) an encryption key you could.
1) Check to see if current user has encryption key in the store.
1a) If not then create a random encryption key
2) Use key to encrypt file and store
3) To decrypt retrieve key from store.
4) Another user may be able to access the file but will be unable to get a copy of the key from the store.
A couple caveats. Only the windows user who stored the key can retreive the key. However this can be bypassed depending on environment. If the user has no windows password (or weak windows password) anyone w/ access to machine can run as the user and windows will gladly hand over the key. In a domain environment anyone (admin) who can impersonate the user and modify password can access they key. If user's windows profile is trashed so is the only copy of your encryption key.
in my current C# windows application password has been stored in plain text which is obviously not good. so i just want to know what is the best way to encrypt the password and stored into SQL Server. I have read that using hash+salt is better. but i feel "EncryptByPassPhrase","DecryptByPassPhrase" new feature in sql 2005 is better to use because you are handling everything from SQL Server itself and i suppose it uses triple DES. can somebody suggest is it good to use it ?
Do you need to have access to the original password, or are you just going to try and compare an entered password against one in the database?
If you need access to the original password, then you are going to have to use an encryption algorithm instead of a hash algorithm.
If all you're doing is storing a password in the database so that you can check it later against a known input value, then a hash with a salt will work.
Remember that when the client is sending the credentials across to be validated, that you don't want to be sending the password in clear text!
A hash & salt is the way to go, because its impossible to retrieve the original password from it. If you encrypt then decrypt the password, the plaintext password is retrievable so its not the best.
I agree it makes sense to have the encryption all in 1 place. However if you separate the key from the data (key in the c# code, data in the db), that will increase security. Also, Sql Server uses a master key when encrypting, which means if you need to restore the data to a new server, you will have trouble restoring the data.
This all comes down to key management and how you want to do this.
As with most questions the best answer depends on the context of your situation. There is no good solution.
Some options:
Leave the password in plain text or reversably encrypt. Use SQLServer facilities to encrypt important fields at the RDBMS level or use similiar encryption functions and hope that MS has implemented reasonable key management and the keys are reasonably secure for your purposes. In practice all encryption does is collapse storage of a whole lot of little secrets into storage of one big secret.. It might make the problem more managable but the problem itself never goes away.
Irreversably "Encrypt" the password using a hashing algorithm or some form of crypt(). Depending on the attack vectors available this method may not provide much in the way of actual improvment of security over plaintext storage.
. Use of hashed passwords limits your options in terms of selection of a secure authentication algorithm. With this approach you will likely end up sending plain texts or other material that is no better over a transport (regardless of if unbound encryption is used or not) this can be a substantial risk from a trust POV.
. Succeptable to offline dictionary attack if hashes are stolen recovery of some portion of passwords should be outright assumed if they have any value to an attacker.
. In some cases knowledge of the password hash can be just as bad as knowing the password in terms of system access.
If you are certain that you will never use a hashed scheme to authenticate (like HTTP Digest Auth), hashed password is more secure. To avoid rainbow table attack, please use a nonce (or salt). I would use HMAC-SHA1 and use the nonce as the key. They key must be stored with the password.
Otherwise, you will have to store encrypted password because hashed password can't work with authentication involving hashes. For encryption, I have following suggestions,
Don't store the key in DB, don't hardcode it either. Store it some other secure place, like using DPAPI on Windows.
Make sure you have a key version so you can rotate the key to comply with certain standards.
I am not familiar with the encryption in SQLServer. Make sure it has a random Initial Vector. You can check this by encrypting same password twice, it should yield different ciphertext. If no random IV, don't use it, just encrypt it in your application.
I'm in a bit of a strange dilema. Please bear with me as I try to explain it!
I'm using forms authentication and am storing additional user information in another table (referenced UserID from Forms Auth, encrypted SSN, Salt value). When users register to the site, I ask SSN, DOB and LName and verify against our system before they create an account. I want to determine if that SSN has an account associated with it in forms authentication. Since the SSN is encrypted with a salt value, I can't do a lookup without looking at each row.
I only want 1 user account per SSN. Using a salt value disrupts this.
The way I see it, the only way around this is to use a common encryption algorithm for the SSN. When the user types it in, I apply the same encrypt algorythm and see if there is a value match in the user extended properties table.
Is this secure enough?
Rather than use the same salt value, generate the salt based on the other user information so that it can be reconstructed. Thus, you can regenerate the salt once the user applies, and you can generate the expected hash and get the job done in a single query.
If you wish to encrypt (not hash) the SSN value, it is not a good practice to store the key in the same table as Natso has pointed out. This is fraught with danger, since keys are not to be stored with the data they protect - if an attacker manages to obtain a dump of your database, he would be able to decrypt the encrypted contents, since the key is stored along-side.
The application should obtain the key from a secure key store which could then be used to encrypt/decrypt the information. This way, you could continue to store sensitive information in the database thereby protecting your information, and apply a different mechanism (usually file-system security) to protect your key store.
This is of course, assuming that your requirement is to store data in a secure manner in the database, and recover the same at a later point time. However, if you do not the data to be recoverable once it has passed through an algorithm, you should explore the use of hashes.
Use the same salt every time. Then you can compare the encrypted values.