Does DPAPI automatically do Dynamic Salt? - c#

I'm looking into using Windows' Data Protection API (DPAPI) to encrypt some data. One requirement I have is to use a Dynamic Salt when encrypting values.
I have noticed through testing that if I encrypt the same string multiple times, I get a different result. This is with using the same string, null Entropy value, and same scope.
This makes me FEEL as though there is a dynamic salt involved already. I am not seeing any documentation stating this.
Here is the method I am calling https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.protecteddata.protect?view=netframework-4.7.2
.
Does DPAPI handle dynamic salting already? If not, what is causing the encrypted values to change each time?

The MasterKey, however, is not used explicitly to protect the data.
Instead, a symmetric session key is generated based on the MasterKey,
some random data, and any additional entropy, if an application
chooses to supply it. It is this session key that is used to protect
the data.
[...]
The session key is never stored. Instead, DPAPI stores the random data
it used to generate the key in the opaque data BLOB. When the data
BLOB is passed back in to DPAPI, the random data is used to re-derive
the key and unprotect the data.
https://msdn.microsoft.com/en-us/library/ms995355.aspx
This random data included in the encrypted data acts as a salt.
The intention of the optionalEntropy parameter is to allow individual applications to protect themselves from other applications running under the same user account and is not required to increase the effectiveness of the salting already performed.

Related

ASP.NET MVC Hashing Sensitive Data (EF)

My client requires me to store certain database information hashed. Since Entity Framework hashes account passwords by default, is there a quick and easy way to hash other database columns as well?
I would advise to Encrypt : Encryption Example
You can than add attribute [Encrypted] to the properties you want to encrypt
A hash is a one-way function. Hashing something renders it irretrievable - as in, the actual value can never be recreated.
For passwords, this is exactly what you want, because you never need to display a user's password to them, you just need to check they typed the correct one. For most data, you need to be able to use it. Therefore, what you're looking for is encryption, not hashing.
Have a look at AES256 for encrypting the data before it goes into the database. You might also consider transparent data encryption, if you're using a managed database. Note that if you encrypt the values that go in yourself, you won't be able to query on them or index them - so you can only do it for values that you don't need to look up.

AES Key Management advice

I need some advice on a school project I am working on. I am making an AES app for encrypting data in some files. Now these files can be accessed by many people.
For the AES key, I was thinking of using RFC2898DeriveBytes to get an encryption key from a passphrase. MSDN has some good tutorial on how to use it. Now, my problem is Where and how to store that key?
I wanted to store the key in a file in a flash drive, but if there are many users, then how to write the key to many flash drives at the same time? (A computer can have only a limited number of ports). Also, lets say I have a new user who should have access rights to some file, how do I write the key to his flash drive?
It really depends on the goal of your application.
If the intent is to encrypt the data such that any user of your applicaiton can access it, then it is more appropriate to embed the key (or, even safer, data from which to derive the key) in the application itself.
If access is to be restricted on a per user basis, then the key (or data from which to derive the key) will need to be stored on a per user basis (so that it is only available to authorized users).
A couple tips on using embedded security data:
break the data up into pieces that can be pulled from various places within the application. Use a custom algorithm to assemble the data.
it is much safer to embed data from which to derive your key than to embed the key itself. If a hacker uses a binary editor and finds your key intact in the application, it will be much easier to decrypt the files. If the same hacker finds the data from which to derive the key, he still must determine the algorithm you've used to derive the key from that data before it would be usable.
You cannot store the key; you would have to tell the user what the key is. The RFC2898DeriveBytes is useless if you simply store the output. If you need a random key, use a well seeded random number generator instead.
Normally you would encrypt a random data key with the key that is generated from the users password. Then use the data key to encrypt the data. This way you can encrypt a file for multiple users; just encrypt the same key with those of the users (generated with the PBKDF2 function in RFC2898DeriveBytes) as you do now.
Make sure you use a different salt for each time that a user enters his/her password. It's also strongly recommended to prepend a random IV to the data file, and to use authenticated mode encryption or a (H)MAC.
Personally I wouldn't store the key anywhere - just require them to enter the password and generate the key on-demand.

How is SecureString "encrypted" and still usable?

According to MSDN SecureString contents is encrypted for additional safety so that if the program is swapped to disk the string contents can't be sniffed.
How is such encryption possible I wonder? The algorithm would be fixed and therefore either well-known or deductible (say one of seven widely used in industry algorithms) and there must be a key somewhere in the program. So the attacker could fetch the encrypted string, fetch the key and decrypt the data.
How can such encryption be useful?
I'm quoting from an article about the DPAPI which is used to derive the key. This should answer most questions that you have about SecureString.
And yes, SecureString has drawbacks and is not completely secure, there are ways to access to data, for example, injecting Hawkeye into the process is mentioned on MSDN as a way to extract the SecureString. I have not personally verifed this assertation.
DAPI Key Management
DAPI is a symmetric based encryption technique, which means it uses the same key to both encrypt and decrypt data. Before getting to some examples of how to use DAPI it's worth covering how DAPI manages its key. For the most part DAPI key management process is invisble and you generally don't need to worry about it, which is the main reason why DAPI is a good approach.
In the introduction I wrote that the master key is generated from the user's login password. This isn't the complete picture. What actually happens is Windows uses the user's login password to generate a master key. This master key is protected using the user's password and then stored along with the user's profile. This master key then gets used to derive a number of other keys and it's these other keys that are used to protect the data.
The reason why Windows does this is it allows applications to add additional information, called entropy, to the process of generating the individul keys. You see if every application running under the user's login account used the same key then every application could unprotect DAPI protected data. Sometimes you might want applications to be able to share DAPI protected data; however, sometimes you won't. By letting the application contribute entropy to the generation of a key then that key becomes application specific and any data that is protected by that application can only be unprotected again if they know the entropy.
Although generating a master key, and then using that master key to generate other keys to do the actual encryption, might seem like a long winded approach it does have one major advantage. Since there is an additional level of abstraction between the user password protected master key and the actual keys used to protect the data it means that when the user changes their password then only the master key need to be re-protected; none of the protected data needs to be re-protected. Since the master key is much smaller in size than the data then a significant performance saving is made.
When the user's password changes then of course a new master key is generated. This new master key is then used to generate new individual keys. However, since all the previously generated individual keys were derived from the old master key then Windows needs to store all previous master keys, which it does. Windows never forgets a master key and all protected data is marked with a GUID that indicates which master key was used to protect the data. So in terms of adaptability DAPI is able to cope with changes to users' passwords, while ensuring a) that protected data doesn't need to be re-protected, and b) that keys used to previously protect data as still available, and c) it does all this automatically for you.
Unless the computer is a member of a domain DAPI can only unprotected data on the same machine that was used to protect it.
As well as allowing user level protection, in that master keys are based on user passwords and protected data for one user cannot be unprotected by another user, DAPI also provides machine level protection, in that the master keys are based on machine specific information. Machine level master keys allow applications to store protected data so that it can be unprotected by all users of the application. The only difference in the process already described is the master key is generated from machine specific information not user specific information.
I looked at one point into the code for it and it uses Windows's advapi32 to do its dirty work. So the key isn't stored in the application's memory.
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
internal static int SystemFunction040([In, Out] SafeBSTRHandle pDataIn, [In] uint cbDataIn, [In] uint dwFlag)
Which is better known as RtlEncryptMemory.
It decrypts with RtlDecryptMemory (SystemFunction041).
I'm sure the compiler does something with the SecurityCriticalAttribute as well.
edit this was reflected using 4.0. other versions might different.
As others have already answered, the contents of SecureString are encrypted using DPAPI, so the keys aren't stored in your application, they're part of the OS. I'm not 100% positive, but I would assume that SecureString uses a user-specific key, so that even if another process gains access to the block of memory, it would have to be running under the same credentials in order to simply decrypt the content using the DPAPI. Even if not, the machine key (in theory) prevents the string from being readily decrypted if transferred to another system.
More important with SecureString is how & when you use it. It should be used to store string data that needs to be retained in memory for "extended" periods of time, but which are not frequently needed in their decrypted form. At some point, you're going to have to decrypt it into a regular old System.String, or a System.Char[]. This is when it's most vulnerable in memory. If you do this too often, then you have multiple copies of the decrypted string floating around in memory waiting to be collected.
As a general rule, if I'm reading encrypted data (say login credentials) that I need to retain for infrequent use (PayPal or Amazon API interaction, for instance), then I store/cache those credentials as SecureString, then decrypt it as-needed only long enough to make the web service calls, and ensure that the lifespan of any decrypted copy is only a few lines of code.
It's probably also wise to use critical blocks or similar to hint to the CLR that it should not context-switch while the decrypted string is in use, to improve the chances that any decrypted copies are collected before the memory is cached or swapped.
By the magic of DPAPI:
This class stores its data using the Data Protection API (DPAPI) protected memory model. In other words, data is always in its encrypted form while it is stored inside of a SecureString. The encryption key is managed by the local security authority subsystem (LSASS.EXE), and through the DPAPI, the data can be decrypted via interprocess communication.

How should I derive the key and initialization vector for my AES encrypted database entries?

I've built a CMS system to allow users to create and manage online forms on my client's intranet app.
Of course some of the data handled by the forms may need to be encrypted e.g. if the system is used to build a form that handles salary specifics or whatever. So I'm using the AESManaged class to symmetrically encrypt this sort of data prior to it going into our application db.
All is fine, but now, prior to release, I could do with a steer regarding the shared secret and salt.
My original idea was to make a (dynamic) shared secret by combining the (GUID-based) ID of the Form containing the encrypted field with the (again, GUID-based) id of the Question the field is the answer to:
FormId:QuestionId
My Salt is currently generated the same way, only with the order of Guids reversed ie.
QuestionID:FormID.
I'm new to this stuff so not sure if this a sensible strategy or if I should be doing it some other way?
The salt should be a randomly generated value. Its purpose is to make dictionary/brute force attacks more difficult to execute. Wikipedia has a nice article on cryptographic salts:
http://en.wikipedia.org/wiki/Salt_(cryptography)
For the shared secret ideally it would not be a value that was stored unencrypted with the data that it was encrypting (such as your ids). It's generally a best practice that the key be chosen somehow by the end-user or admin so that they could rotate it periodically or if some sort of security breach occurred. This password key could be owned by each user of the CMS or perhaps by an admin account. If you have very serious security requirements you could pursue a third-party Key Management Server.
If the main goal here is more of obfuscation and the CMS will not be subject to some form of security audit then something along the lines of your initial idea would do. It would prevent the casual access of the data but would probably not pass an audit against formal standards that would require a random salt, a way to rotate the keys, and a way for the "owner" of the system to change the password such that you yourself could not access the data.

How to encrypt a password for saving it later in a database or text file?

I want my application to save the password encrypted in a database or in a text file.
How can I do that assuming that the database or text file can be open by anyone?
Duplicate
Encrypting/Hashing plain text passwords in database
Not duplicate
I'm asking for code specific for .NET
EDIT: I'm saving the password for later use. I need to decode it and use it to login.
It doesn't have to be super secure, it just needs to be unreadable to the human eye, and difficult to decode with a trivial script.
StackOverflow readers don't know how to write secure password schemes and neither do you. If you're going to do that, save time by sticking with plain text. From Enough With The Rainbow Tables: What You Need To Know About Secure Password Schemes:
Rainbow tables are easy to beat. For
each password, generate a random
number (a nonce). Hash the password
with the nonce, and store both the
hash and the nonce. The server has
enough information to verify passwords
(the nonce is stored in the clear).
But even with a small random value,
say, 16 bits, rainbow tables are
infeasible: there are now 65,536
“variants” of each hash, and instead
of 300 billion rainbow table entries,
you need quadrillions. The nonce in
this scheme is called a “salt”.
Cool, huh? Yeah, and Unix crypt —-
almost the lowest common denominator
in security systems —- has had this
feature since 1976. If this is news to
you, you shouldn’t be designing
password systems. Use someone else’s
good one.
Use BCrypt - Strong Password Hashing for .NET and Mono. It's a single cleanly written .cs file that will continue to meet your needs as password cracking computers get faster.
BCrypt - Strong Password Hashing for .NET and Mono
Triple DES is one way to do it, as long as you mean "A password that my system needs to be able to recall in order to access a resource". If you mean the password is something a user needs to be able to gain access to your system, probably don't want encryption, just a hash will do. When you store the hashed password value, it is useless to anyone with direct database access, but can still be used for authentication. All you do is compare the stored hash against a hash of the incoming password. If they match, then you grant access.
It isn't perfect, by any means, but it is the way 99.999% of people store their passwords.
If you want to argue that you wish to provide the password back to a user if they lose/forget it, then please don't. Issue them with a temporary password (which you store hashed in the db) and get them to change it on first login.
Use Data Protection API either with the user or machine store (e.g. different key per account your program/database server runs under vs. one key per machine). This will help you decode the passwords later and you don't have to remember or store any encryption keys. The downside of it is that when you reinstall the system/delete the account you won't be able to recover the data, I believe.
If you use encryption for securely storing passwords, you'll need to store the encryption "key" somewhere, too. This will be the "weak link", since if someone gets hold of the encryption key, they will be able to decrypt the encrypted passwords.
Since this is passwords that we're talking about here, a much better solution is to use a one-way hash. You hash the password when the user first creates it (preferably hashing with a salt value) and store the resulting hash value. Since hashes are one-way, no one can reverse the hash to the original plain text value.
To check that a users password is correct, you simply ask the user for the plain-text password, hash their input again and compare the resulting hash value with the hash value you have stored (taking salts into account of course). If the two hash values are the same, the user has entered the correct password.
Please see the following links for further info:
Hashing Password with Salt
For encryption (if you need to use that), I'd use Rijndael (AES).
Based on your question I can see two approaches depending on why you are storing the password.
A. if you only need to authenticate using their password and nothing else.
In that case, going using an algorithm that is not reversible (Hashing) would be your best choice. You will need to make sure of a couple of things:
Make sure that the connection is encrypted when transmitting the password from the client to the server. This will prevent it from being sniffed out. This is pretty trivial to do with web applications since the web server is doing the heavy lifting for you. If not it gets a lot tricker and is the subject of an whole other question.
Choose a solid hashing algorithm to prevent collision. I would recommend SHA-256 even if it does provide a larger result than SHA1 or MD5. The reference from Microsoft on using their implementation of the algorythm is here.
Salt the password to prevent attacks using rainbowtable (i.e. looking up the password in large table with the precomputed hash and the associated password in clear text). The answer here (sited in your question) gives good pseudo code in Python on how to do it. There is also a good example of .NET code here.
B. if you need to be able to read the password for each user for other purposes than authenticating the user.
This case is easy if we are only talking about storing a password (or any kind of sensitive information) on a single computer (server). If that's the case, using the Microsoft Data Protection API would be a good solution since it is tied to that computer and (depending on the way you work) the user under which you application runs and takes care of the worst of the job for you (creating, storing, and using keys). You can find some code reference from Microsoft here. If you need it on more than one system and are not willing to enter the password on each system you install on your application then things get a lot more complex because you need to implement a lot of it from scratch. That would be the subject for another question I would think.
If you need to decrypt the password for later use and it doesn't have to be SUPER secure, then use the method here:
http://support.microsoft.com/kb/307010
It's well documented, and easy to understand.
do you need to encrypt it ever again? otherwise use a hashfunction to encrypt it and encrypt the password given by the user with the same hashfunction and look if the hashes are equal.
The reason for not using a 2-way-encryption is that one cannot decrypt your key - since a good hashfunction has collisions.
Personally, I would use something that has one-way encryption - MD5, SHA1, etc...
You can use the FormsAuthentication class with it's HashPasswordForStoringInConfigFile method. When validating the user, encrypt the entered password and compare it with the stored version.
Like ocdecio I would use TripleDes, I would also save the salt in the database too. The key for me is usually hard coded, but the salt should change for each encrypted item.
If you just need the password for an internal authentication process, you should not save the actual password, but save a hash of this password. When you need to check if a password is valid, you'll have to run the hash function on provided password and compare it with the hash you stored in your database/file. You can never find the original password from the hash.
If you need to keep the original password, you'll have to encrypt it. You can use for example a public key infrastructure if you have a process that writes the passwords (public key) and another one that reads them (private key).
Do you really need to be able to retrieve the password itself? If you're storing a password for the purposes of authenticating someone (or something), you should rather hash it (with salting) and then compare that hash to the hash of the password supplied by the party wishing to be authenticated.
If, on the other hand, you need to store the password in order to be able to retrieve it and supply it to some other authentication service later, then you might want to store it encrypted. In that case, use any decent symmetrical encryption algorithm you can, such as TripleDES or AES or Blowfish.
Briefly:
Get a big random number which you will keep private and only your application code will have access to.
Encrypt the password + random number with an ancryption algorithm like SHA1, most programming languages have a cryptography framework.
Store the hashed password.
Later when you want to check inputted passwords, you can rehash the user input and compare to the "virtually" undecipherable stored passwords.
Here's a string encryption article with example code .NET
http://www.devarticles.com/c/a/VB.Net/String-Encryption-With-Visual-Basic-.NET/3/
There is no need to use anything fancy, because anyone with a little bit of skill and determination will break it anyway.

Categories