i was wondering whether AES-256, with a strong key, becomes less secure when some part of the solution is known. as an example scenario, the string i want to encrypt is "my secret password is: du420rfashud". the attacker who tries to get my password knows that the string starts with "my secret password is: ". is it possible to decrypt the rest of the string in this case? also my second question is, if the attacker knows the complete solution, can he derive the key from that?
thanks
The scenario that you describe is called a known plaintext attack (or even a chosen plaintext attack). Good cryptographic ciphers are not vulnerable against those attacks, and that includes the AES family of ciphers.
Basically, no matter how much information you have except the key, finding the key is no easier than brute-force trying.
(Practically, such attacks are quite easy to mount, since all sorts of encrypted communication contains predictable standard headers. Therefore, such a vulnerability would make a cipher essentially entirely useless.)
Related
Recently I have been looking to add some security to a project. I have been doing lots of research into the situation and discovered that clearly password hashing is a must. Further I have concluded that the best options are to use bcrypt, PBKDF2 or scrypt.
Also I have seen much discussion over hashing vs encryption and discovered that it is clear that hashing is more important. That said, after many searches into the depths of Google I have yet to find any information on whether encrypting an already properly hashed password is of any benefit, serves to harm or is relatively neutral.
Is the CPU cost of doing both worth it? Are there any pitfalls?
Encrypting something leads to the need of decrypting, which in turn leads to the problem you already have: secure storage of a secret.
Assuming that you want to store passwords as hashes instead of plain text you are basically doing this:
hashpw := hash(salt + password)
You then store salt and hashpw in a file and use this data instead of the plain text passwords. (Note that the order of the concatenation of salt and password is crucial in many cases and that this is only a visualization of the process, nothing more; Use a tool to generate salted hashes).
A possible attacker then needs to guess the salt and the plain text password to check for a match with
the stored hashpw, which is as secure as the hash algorithm you're using (rate of collisions).
Encrypting something using some cipher has the benefit of being able to restore the plain text, which
the hashing way does not offer. It also requires the system which decrypt the cipher text to have the
key available. Say you encrypt a string foo with some key bar. To decrypt the resulting cipher text
brn you need the key bar again. This key needs secure storage on your system and if the key is exposed
to the attacker, all security is gone.
As a general rule of thumb I would say that hashing provides a good way of storing texts which are
checked against (e.g., passwords) as the security of that is determined by the collision rate of the
hashing algorithm. Encryption on the other hand, is the technique you're using to store the rest of
the data securely.
You're on the right track. Use a key derivation/password hashing function like the ones you've mentioned.
Do not use just a hash or salted hash. The main issue is that traditional hashing algorithms (MD5, SHA-*, etc.) are intended to be fast. That's not advantageous for password storage, and many implementations are breakable, even if you add a salt.
Encryption always introduces key management-related issues. It should be avoided for password storage.
The advantage of a KDF is the work factor. It's designed to be slow and computationally expensive, which is why they're idea for this situation. Scrypt is the most resilient of the options you're looking at since it requires a set amount of memory to execute. This kills the GPU attack vector. There are tradeoffs whichever way you go, but all of your choices are fine as long as you use appropriate work factors where they're configurable.
I would simply encrypt the password. Hashing is fast, but a little unsafe for passwords. When I use hashing for security purposes, it's usually for things like message signing e.g. message + hash(message+password) so that the message can be verified, but I'm no expert in the field. I don't see the point of doing both.
I was wondering if it is common practice to encrypt a password hash, and/or the salt, does it necessarily make it more secure or just increase the time it'd take to "guess" the password?
Thanks!
It's not common practice to encrypt a salted hash. It may slightly increase security but realistically it's not worth it, since you'd have to manage the key in some way, complicating the whole process. Using a salted hash with a secure hashing algorithm will be fine.
Generally, you don't need to encrypt hash as long as you use good cryptographic hash function. As for salt, salting is done best before encrypting, ie. salt does get encrypted. The exception would be one-time table, in which case you can easily salt afterwards. As for the third question, whole encryption is nothing but increasing the time it takes to "guess" the plaintext, exception being again one-time table. Now what's your concrete problem? Can you formulate it as a task in some concrete computer language?
If the hash was produced by a "good" algorithm, than it doesn't make any sense to cipher it, since you would be essentially ciphering something that in theory only the rightful user can generate.
Ciphering the salt doesn't add any kind of real security.
Somehow I don't get HMACs.
I once asked Why do I need HMACs when we do have public key signatures?, and I think I got this one. Easier to compute, and so on ...
But, what I do not get is why we need HMACs at all, respectively what kind of problem they are solving.
From my understanding, HMACs ...
provide a way to make sure the message has not been tampered,
are "secured" by a secret, but symmetric key.
Hence for calculating the HMAC (either initially or for verification) I do need to know the secret key.
Now, if I can exchange this key in a secret way without it being tampared, I could also exchange the message in the very same secret way without it being tampered, don't I?
Okay, now you could argue that you only need to exchange the key once, but you may have multiple messages. That's fine.
But if we now have a secret key that must be kept secret by all parties, we could also directly use symmetric encryption using the very same secret key to encrypt the message, couldn't we?
Of course, an HMAC shall provide a solution against tampering, but if I only have an encrypted message without the secret key and a reasonable encryption algorithm, I can not change that encrypted message in a way that a) decryption still works, and b) a meaningful decrypted message appears.
So what do I need an HMAC actually for?
Or - where is the point that I am missing?
You're assuming that it is impossible to tamper with an encrypted message without knowing the key used for encryption. This is not the case and a dangerous assumption to make. There are several things possible even if you only have access to the ciphertext:
Corruption of a suffix of the message: this can leak information about the content through error messages, timing and possibly other ways.
Corruption of ranges of the message for some modes (ECB, CFB and possibly others): same as above but the attacker has more ways to trigger the wanted behaviour.
Flipping of arbitrary bits in a single block (not knowing their initial value though) and corruption of the following block (CFB): If some bits are known to the attacker he can set them to the value he wants.
Flipping of arbitrary bits in the whole message for stream ciphers or stream cipher equivalent modes for block ciphers: This can avoid corruption altogether.
Thus it is very important to verify that no attacker tampered with the message before processing even a single byte of the decrypted content. Since there are again some pitfalls in doing this using ad-hoc verification or simple hashing there is a need for MACs of which HMAC is one example.
I wrote a "Password Locker" C# app a while ago as an exercise in encryption. I'd like to move the data to the web so that I can access it anywhere without compromising my password data. I'd just like to run my ideas by the community to ensure I'm not making a mistake as I'm not an encryption expert.
Here's what I envision:
In the C# app all the password data is encrypted as a single chunk of text using a user supplied password. I'm using Rijndael (symmetric encryption) in CBC mode. The password is salted using a hard coded value.
Encrypted data gets sent to my database
I go to a web page on my server and download the encrypted text. Using client side javascript I input my password. The javascript will decrypt everything (still client side)
Here are my assumptions:
I assume that all transmissions can be intercepted
I assume that the javascript (which contains the decryption algo, and hard coded salt) can be intercepted (since it's really just on the web)
The password cannot be intercepted (since it's only input client side)
The result is that someone snooping could have everything except the password.
So, based on those assumptions: Is my data safe? I realize that my data is only as safe as the strength of my password... Is there something I can do to improve that? Is Rijndael decryption slow enough to prevent brute force attacks?
I thought about using a random salt value, but that would still need to be transmitted and because of that, it doesn't seem like it would be any safer. My preference is to not store the password in any form (hashed or otherwise) on the web.
Edit:
I am considering using SSL, so my "interception" assumptions may not be valid in that case.
Edit 2:
Based on comments from Joachim Isaksson, I will be running with SSL. Please continue breaking apart my assumptions!
Edit 3:
Based on comments from Nemo I will use salt on a per user basis. Also, I'm using PBKDF2 to derive a key based on passwords, so this is where I'll get my "slowness" to resist brute force attacks.
Without even going into the crypto analysis in any way, if you're assuming all your information can be intercepted (ie you're running without SSL), you're not secure.
Since anyone can intercept the Javascript, they can also change the Javascript to make the browser pass the clear text elsewhere once decrypted.
Also, anyone hacking into the site (or the site owner) can maliciously change the Javascript to do the same thing even if SSL is on.
By "password data", I assume you mean "password-protected data"?
The salt does need to be random. It is fine that is transmitted in the clear. The purpose of a salt is protection against dictionary attacks. That is, should someone manage to obtain your entire encrypted database, they could quickly try a large dictionary of passwords against all of your users. With random salts, they need to try the dictionary against each user.
Or, alternatively, even without compromising the database, they could generate a huge collection of pre-encrypted data for lots of dictionary words, and immediately be able to recognize any known plaintext encrypted by any of those keys.
Even with a salt, dictionary attacks can be faster than you would like, so deriving key data from a password is a lot more subtle than most people realize.
Bottom line: As always, never invent your own cryptography, not even your own modes of operation. To derive an encryption key from a password, use a well-known standard like PBKDF2 (aka. PKCS#5).
Well, as this is an open question:
Issue #1
What are you going to do if the password that is supplied is incorrect, or if the salt/ciphertext is altered? You will get an incorrect decryption result, but how are you going to test that? What happens if just the last part of the ciphertext is altered? Or removed altogether?
Solution: Provide integrity protection against such attacks. Add a HMAC using a different key or use a mode like GCM mode.
Issue #2
What happens if you change or add a few bytes to the password (compare the encrypted store in time)?
Solution: Encrypt your key store with a different IV each time.
That's already 4 issues found :) Cryptography is hard.
I tried to research this, but there were still some questions left unanswered. I was looking into figuring out how an 8 character password gets turned into a high-bit encryption key. During my research I found articles that would talk about the salt value.
Assume you could get all 256 characters to play with, then an 8-character password would be 64-bits long. So, the remaining 64 bits is simply a salt value. And, correct me if I'm wrong, but this is done so that if someone was going to try to try ALL the possible values (brute force) they'd have to try all 128-bits since even the salt is unknown.
My questions really relate to this 'salt' value:
When someone makes an application, is the salt value hard-coded into it? And if so, can't it be obtained through reverse engineering the executable?
If the salt is generated at random, then I assume it must have some way to duplicate it. So, isn't that function that returns a random salt able to be reverse engineered to force it to duplicate itself to get the salt value?
This might be out of the scope, but if a salt value is generated on a server side (of a client/server relation), then wouldn't it have to be shared with the client so they can decrypt data sent by the server? And, if it's being sent over to the client, can't it be intercepted which makes it useless?
Is there some other method that is used besides this 'salt' value that can turn an 8-character string into a strong encryption key?
As usual with security-related questions, this answer's going to be a long one.
First, the simple answer.
Q: How does one turn an 8-character string into a 128-bit key?
A: One doesn't.
This is a truthful answer. Now, one that's more appropriate to what you're asking:
A: Create a random 64-bit value, and store it with the password in the database. Now, the password is half the key, and the random value is the other half.
This one is a lie. Here's what you actually do:
A: Hash the password along with a random salt using a method producing 128-bit or longer output. Use 128 bits of that as the key. Store the salt.
Now to address your questions on salt. First off, the purpose of salt is not really to lengthen encryption keys. It is to prevent people building rainbow tables - mappings from hashed to unhashed forms. To see that your encryption is no stronger, just imagine the attacker knows your key-extending algorithm. Now, instead of guessing 128-bit keys, he just guesses your 64-bit password and then uses the same algorithm. Voila. If the salt is unknown to the attacker, yes, you've gained a bit, but they must already have your ciphertexts to attack them, and the salt must be stored in the plain along with the ciphertext. So this is an unlikely scenario.
Salt is random per encryption key.
Random means random. If you are insufficiently random when you use a cryptography algorithm which assumes unpredictable material, you are vulnerable. That's what /dev/random is for - the system entropy pool is very good. Get a better hardware RNG if you're worried.
Yes, if you salted the key, someone needs the salt to decrypt things you encrypted using the salted key's hashed value. No, sending the salt does not necessarily compromise your data; send the salt only to someone who has proved they already have the password, but it's stored in your database next to the ciphertext. As mentioned above, someone needs both the salt and the ciphertext to mount an attack. Again, the purpose of the salt is not to raise the strength of the encryption, it is only to prevent precomputation attacks against your hashes.
There are methods of key extension. But, fundamentally, your protection is only so strong as its weakest link, so to provide 100% unbreakable encryption you will need a one-time-pad (a truly random key as long as the data to be encrypted). In the real world, what is usually done is hashing the password along with a salt to produce unpredictable longer keying material.
The function that turns a password or passphrase into a cryptographic key is called a Key Derivation Function (this might help you searching for more information on the topic). Such functions take a password and a randomly generated salt, and produce a key through a process that is deliberately computationally intensive. To reproduce that key, you must have both the password and the salt - so you are correct, the salt must be stored or transmitted along with the encrypted data.
The reason that Key Derivation Functions use a salt is to increase the work factor for any attacker. If a salt was not used, then a given password will only ever produce one single key. This means that an attacker can easily create a dictionary of keys - one key for each word in his dictionary. If, on the other hand, a 64 bit salt is used then each password can produce ~2**64 different possible keys, which expands the size of the dictionary by the same factor. This essentially makes producing such a dictionary ahead-of-time impossible. Instead, the attacker has to wait until he's seen the salt value, and then start generating keys to test. Since the key derivation function is computationally expensive, this is slow, and he won't be able to get far through his dictionary in a reasonable timeframe.
1) Each password is salted differently, and the salt is stored with the hash.
2) It's stored.
3) No, the client never decrypts anything. It sends the password, which the server salts, hashes and compares.
4) Yes, I'll add a few links.
Salts are generally not hardcoded, but they are generated at random, usually server-side, and never communicated to the user.
The salt would be stored in a database, separate from the passwords. The idea is that even if the password hash database is stolen, it would be very difficult to get the actual passwords (you'd have to try a lot of combinations), without having the salts as well. The salts would be generated at random, and different for each user, so even if you found it out for one, you'd still need to find all the others.
The salt is never sent, because the client never decrypts anything. The client sends the password to the server, the server adds the salt (which is randomly generated and stored for each user, and the user never know it).
So basically on this is what happens.
On registration:
User sends password to server.
Server adds a random salt to the password and then hashes it.
The salt and final hash are stored in separate tables.
On login:
User sends password to server.
Server fetches stored hash, and adds it to the password.
Server hashes the password and salt.
If the final hash matches the one in database, the user is logged
in.
...Is there some other method that is used besides this 'salt' value that can turn an 8-character string into a strong encryption key?
YES but...
You can compute the hash of that 8-character string:
For example if you need a 256 bit key:
key-256bit = hash(8-character string) //use SHA-256 - very secure
key-128bit = hash(8-character string) //use MD5 no more considered secure
"into a strong encryption key?" about strong.... depend how strong you need it because if you use only a 8-character string it mean that you could only create 2^8=256 different hash values and that's an easy task to brute force!!
conclusion: a salt would be of great value!
cheers
Daniel