9

I am currently working on an application that encrypts files with AES 256.

The problem is that I want the user to see whether the password is wrong before the file is decrypted.

For example if you want to decrypt a file that is about 1GB big it takes you 20 minutes to decrypt it, but only after the decryption do you notice that the password was wrong, and you have waited 20 mins for nothing!

So there must be a possibility to check the password before decryption. So, you need to transmit the password with the file.

But how? MD5 can be cracked. SHA might also be cracked soon.

So what is the best way, how can I encrypt the password super secure?

AviD
  • 72,138
  • 22
  • 136
  • 218

7 Answers7

8

I want the user to see whether the password is wrong before the file is decrypted.

Decryption does not tell you whether the password was correct. If you supply the wrong password, you will get a decrypted result. A wrong one, but how do you know?

Usually the data that you encrypt has some structure that's known in advance. Say, it's a text file, and it must contain only printable characters. Or it's a video file and must begin with a well-formed MPEG header. If the password is accidentally wrong, then the probability that the output still has this structure is negligible. In most cases the first few decrypted bytes will give away whether the output is well-formed, and therefore whether the password is correct. But it's difficult for your application to tell — whether it performs that verification after decrypting the first few bytes or after decrypting everything — unless the application is specialized to a specific file format.

So what you can do is to start your plaintext with a known header, something like Elefantosque's exercise in password-protected encryption. If the first few decrypted bytes are correct, then you know the password is correct. The length of the header is determined by the strengh of your encryption; it should be at least the length of the secret key (i.e. 32 bytes here).


Incidentally, if your decrypting application can tell whether the output is correct in some generic way, then it is doing more than encryption: it is also verifying the integrity of its input. AES doesn't do this (it can if used in particular modes). So either your application is performing some other cryptographic verification of the data which you aren't telling us about, or your application is not really verifying integrity, and in particular does not detect a wrong password.

If you use the known header method above, then your application will detect a wrong password by verifying the integrity of the header (here, the integrity check is that the header must be equal to a known value). Note that you will still not be verifying the integrity of the data.

If you're worried about an attacker modifying the data in transit, then what you need is either some form of authenticated encryption in a single algorithm (which can be an AES chaining mode), or to combine encryption with authentication through a MAC (encrypt-then-MAC or MAC-then-encrypt).

Another thing that you aren't saying is how the use of AES relates to the supplied password. An AES-256 key normally consists of 256 bits which must be wholly unknown to the attacker (randomly generated over the whole key space). A password is a string, usually chosen by a human, which may have constraints to consist only of printable characters, have minimum length requirements and so on. Making an AES key out of a password is a non-trivial operation, and the way you do it is critical to your application (or rather your protocol)'s security.

An acceptable way to make an AES key from a password is key stretching and salting. The problem with passwords is that an attacker can often crack them by brute force. It doesn't matter how your password is used, if the attacker knows that it's one of password, 1234 or l33t, then the attacker can try all three possibilities. The most you can hope for (in a scenario like yours) is to make it expensive for the attacker to try many possibilities. A good stretching function takes a long time to compute. For legitimate uses, you only perform the function once, so the cost doesn't matter, whereas the attacker's cost is multiplied by the number of attempts he performs. As for salting, it lessens the amount of reuse for an attacker who wants to crack multiple encrypted files. Salting means including a random component (stored in plaintext) in the stretched data. As the salt is different for every file, the attacker cannot precompute a list of stretched keys derived from common passwords.


As a more general note, you seem to have a lopsided view of security (don't worry, it's common with beginners). You're putting a lot of importance on the choice of algorithm (AES-256, dismissing SHA-1), and none at all to other parts that matter, such as what makes you conclude that a password is correct or how you use the password in your scheme. In fact, finding weaknesses in a commonly-used cryptographic algorithm is very rare (especially practical weaknesses) compared to finding vulnerabilities in protocols, i.e. in the way the information flows and the algorithms are used. Cryptographic algorithms are hard to design, but a few of them suffice for most purposes and you don't need to understand why they work (or even how, really) to use them. Protocols are hard to design as well, and they are often application-specific, at least in part; so you need to pay a lot of attention to your protocol design. Reuse existing protocols whenever possible (but be careful that you're using them correctly!), and tread carefully when you need to design one. Again, you can bet your application will break because of a broken protocol (or a broken implementation, if you aren't a careful implementer), not because of a broken cryptographic algorithm.

As a matter of fact, there's no good reason not to use AES-128. It would cut down on the decryption time and not perceptibly reduce security. The use of SHA-1 has indeed not been recommended for a long time, though the attacks that were feared took longer to arrive than predicted. Still, SHA-1 is not broken for the purpose that would have mattered here, namely reversing a hash (the known weaknesses have to do with collisions, i.e. finding data with the same hash as some known data). Nonetheless SHA-256 is recommended where the design calls for a cryptographic digest.

P.S. I'm assuming this is a learning exercise. Obviously, for real-world use, you would use existing, well-reviewed software such as PGP/GPG.

Gilles 'SO- stop being evil'
  • 50,912
  • 13
  • 120
  • 179
3

Sorry, what? You need to transmit the password with the file? What type of password are we talking about here, cryptographic evidence, or just "donkey12"?

Short version

If this is for any serious purpose, don't do this. Cryptography is hard. You're not a cryptographer.

Longer version

If you're doing this just for fun, you could do it through a header that you apply to an encrypted file. So C=([header]+[filecontents])

The header will make it easier to verify the password, but also easier for an attacker to work out whether they've got the key right or not when attempting to decrypt it.

It might be simpler (i.e. more secure) to rely on "straight" PKI, and assume the user at the other end won't have a key other than their private key, and that you won't have a key other than their public key.

TristanK
  • 423
  • 2
  • 8
  • 1
    +1 for header to verify, run the header through like 600k times or something to make it so you can't brute force it (let alone it's AES256 so that would be stupidly hard to do anyway). I believe this is similar/the same thing that ZIP does because this implementation sounds terribly familiar. – StrangeWill Jan 19 '12 at 16:59
  • 1
    “The header will make it easier to verify the password”: not really, in practice. The plaintext probably starts with a known header anyway; most file formats do. So protection against brute force decryption attempts must come from somewhere else (which would be the way the key derives from the password). That format-specific header is known to the attacker but not to the application; that's a waste: you might as well get some use of a known header. – Gilles 'SO- stop being evil' Jan 19 '12 at 19:40
  • I inferred the use of multiple arbitrary file formats - it looks like it's a generic file encryption program, so there's no common file format being fed in or retrieved from it. So a header slapped on the front seemed like an easy way of doing that. – TristanK Jan 22 '12 at 21:15
3

I'm assuming the following:

  1. The password you are talking about is for decrypting the file
  2. You are using symmetric encryption i.e. same password for encrypting and decryption
  3. You want to send the password with the file
  4. You are worried about SHA and MD5 as you are considering transferring the hash of the password which the user can use to validate the password prior to using it for encryption. I would not recommend this.

If these are correct then transmitting the password with the file significantly reduces the security benefit of encrypting the file. The reason you encrypt the file is usually to protect against the threats of interception in transit or unauthorized access in storage. Both of which are compromised if you transmit the password with the file.

To get the security benefits you should always transfer the password out of band to the file transmission. Transfer the password via another mechanism preferable secure. E.g. secure email, telephone to an authorized individual, secure USB.

Some suggestions in preferential order:

A) Use asymmetric encryption and move away from passwords.

Use something like open SSL to generate a public private key pair ideally on the recipient machine. Secure the private key with permissions or a hardware security module. Obtain the public key e.g. via email or file transfer, then encrypt the file to that public key. This ensures there are never any password issues and mitigates the defined threats.

B) Write your code or use a program to check the password prior to decrypting

For example this is how Winzip and PGP file encryption using a password works. It will validate the password first prior to decrypting the file. This should address your 20 minute delay problem. If you are not sure how to do this, then it should become another question on stackoverflow with your specific application development language details.

Rakkhi
  • 5,783
  • 1
  • 23
  • 47
2

By making it easier for someone to tell if a password is correct or incorrect, you will necessarily also make a brute force attack easier. So you need to select a password confirmation algorithm that doesn't permit easy brute forcing.

The types of issues MD5 and SHA have do not affect this use. The problem with just sending the MD5 of the password is that someone can use a vast database of MD5 hashes. Unless the password is strong and random, this is a huge issue.

If you're using a random 256-bit key for AES-256, you can just send the MD5 of the key. No conceivable break in MD5 would matter. And on average, 79,228,162,514,264,337,593,543,950,336 different AES-256 keys will have that MD5 hash anyway.

If the password isn't random, you'll want to prevent the use of rainbow tables. You can use a hash with a random tag and include the tag with the hash. A secure solution could work as follows:

1) Generate a random 128-bit value.

2) Hash the password to a 128-bit value.

3) HMAC the password with the random value. (It would do just as well to XOR the two values and hash.)

4) Include the HMAC and the random value in the file.

David Schwartz
  • 4,203
  • 24
  • 21
0

Encrypt with a keyfile or certificate. Encrypt the keyfile or certificate and send. If the user doesn't have the correct password for the cert which would decrypt in next to no time, they can't access the data.

Sonny Ordell
  • 3,476
  • 9
  • 33
  • 56
0

Why do you have to decrypt right away? Can you encrypt a smaller file with their password and if the password works on that, it would work on the larger one?

psuedo code:

if (smallFile.readable == true){
    transmit(password, destination);
else {
    output("You entered the wrong password or username, stupid!")
}

That was more trying to provide a practical rather than secure way of thinking. I relooked at the question and I don't really see a point to this in the first place (as in I agree with TristanK's post). From what I understand, the cryptographic functions are based off of long logarithms so unless you love discreet math and are thinking of getting your PhD in number theory, I'd just use something already developed and tested.

Jeff
  • 646
  • 5
  • 12
-1

How about sending the encrypted password.

When you get the file you enter your password, encrypt it and compare them?