Usability suggestions for Windows app.
Hi all, In my opinion, the password entry dialog is not usable for long phrases, and encourages poor passwords. A checkbox to render the contents visible would be very useful to catch typing mistakes. It is frustrating to be told five times that the two do not match. Not everyone can touch type a long sentence twice with no mistakes. The security in concealing password entry is dubious anyway. It has value for protecting authentication passwords in places where someone may be looking over your shoulder. But would you be working with a highly sensitive document (that is worth protecting with AES) in such an environment? Its contents are as secret as the password used to protect it, and so it makes no sense to conceal the password from prying eyes, yet reveal the document. Another issue with the Windows application is that it performs sanity checks in the wrong order. When you're encrypting or decrypting a document, first you must get through the password dialog. Only then are you told, oops, the destination file already exists and we must bail! There is no security benefit in this; it is just annoying behavior. Why ask for the password if the operation cannot possibly complete (unless someone deletes the file outside of the program). Just bail right away: "We cannot do this operation because the destination file exists." A useful behavior would be to have the option to rename the existing file, or to choose a different name for the newly created file. (Deletion should be deferred to the user, who should be using a secure shred program, at least for the plaintexts). Cheers ...
Kaz,
In my opinion, the password entry dialog is not usable for long phrases, and encourages poor passwords. A checkbox to render the contents visible would be very useful to catch typing mistakes. It is frustrating to be told five times that the two do not match. Not everyone can touch type a long sentence twice with no mistakes.
What I do if I have a really long key is just copy and paste it into the dialog box. I agree that a checkbox to allow one to see the password would be interesting.
The security in concealing password entry is dubious anyway. It has value for protecting authentication passwords in places where someone may be looking over your shoulder. But would you be working with a highly sensitive document (that is worth protecting with AES) in such an environment? Its contents are as secret as the password used to protect it, and so it makes no sense to conceal the password from prying eyes, yet reveal the document.
I don't agree with that opinion. There are many environments where prying eyes exist. It's reasonable to take this kind of precaution. Clearly, it's not perfect. Someone might be able to watch your keystrokes. Or, in the case where I copy/paste a long string, there might be a camera recording what's on the screen. Still, it's better than having nothing at all.
Another issue with the Windows application is that it performs sanity checks in the wrong order. When you're encrypting or decrypting a document, first you must get through the password dialog. Only then are you told, oops, the destination file already exists and we must bail! There is no security benefit in this; it is just annoying behavior. Why ask for the password if the operation cannot possibly complete (unless someone deletes the file outside of the program). Just bail right away: "We cannot do this operation because the destination file exists."
Yeah, it can be a bit annoying to not see the file was already encrypted or decrypted and you type in a long password. On the other hand, you're done: the file you want is already there, so you don't have to do it again.
A useful behavior would be to have the option to rename the existing file, or to choose a different name for the newly created file. (Deletion should be deferred to the user, who should be using a secure shred program, at least for the plaintexts).
If the file is already encrypted or decrypted, why offer to create another version with a different name? Perhaps one is re-using the same filename with different file contents? Paul
On 05.09.2013 15:04, Paul E. Jones wrote:
A useful behavior would be to have the option to rename the existing file, or to choose a different name for the newly created file. (Deletion should be deferred to the user, who should be using a secure shred program, at least for the plaintexts).
If the file is already encrypted or decrypted, why offer to create another version with a different name?
Ah, this is because it's not necessarily the same file. The source file may have changed, and so the target plaintext or ciphertext may be out of date. For instance, you may be working on a document and over the course, encrypt it more than once. Keeping an out of date ciphertext could be handy since the prior version of the plaintext can be retrieved from it. If that isn't wanted, the program could optionally delete or simply overwrite it. (Insecure deletion of ciphertext doesn't raise an issue.) Keeping an out of date plaintext allows the program to avoid implementing secure deletion. The file plain.txt is renamed to plain.txt.1 or whatever, and the user can deal with disposing of plain.txt.1.
Comments below...
-----Original Message----- From: Kaz Kylheku [mailto:kaz@kylheku.com] Sent: Thursday, September 05, 2013 6:40 PM To: Paul E. Jones Cc: aescrypt@lists.packetizer.com Subject: RE: [aescrypt] Usability suggestions for Windows app.
On 05.09.2013 15:04, Paul E. Jones wrote:
A useful behavior would be to have the option to rename the existing file, or to choose a different name for the newly created file. (Deletion should be deferred to the user, who should be using a secure shred program, at least for the plaintexts).
If the file is already encrypted or decrypted, why offer to create another version with a different name?
Ah, this is because it's not necessarily the same file.
The source file may have changed, and so the target plaintext or ciphertext may be out of date.
Right, but that's pretty poor practice. Except for the timestamp, one would not know which is the current version.
For instance, you may be working on a document and over the course, encrypt it more than once.
Yeah, I do that sometimes. In that case, I rename the encrypted files using a date in the name, like "20130905-Whatever.doc.aes". But, to keep the encrypted version and the plaintext version sitting in the same place does not have a lot of value. I tend to store the encrypted versions on an external drive or cloud storage. If I need to constantly keep a set of local files in encrypted state and change them frequently, AES Crypt is not the best tool for that. A better tool is TrueCrypt. TrueCrypt will create encrypted files that can be mapped as a drive (Windows) or mounted (Linux).
Keeping an out of date ciphertext could be handy since the prior version of the plaintext can be retrieved from it. If that isn't wanted, the program could optionally delete or simply overwrite it. (Insecure deletion of ciphertext doesn't raise an issue.)
On Windows, we do not over-write files. On Linux, we do. We get complaints both ways. :-) It's interesting to see reaction people have. By and large, people prefer the Windows behavior of not over-writing files, so we'll likely change the Linux code to behave similarly. What you want is a destructive write option. An "File Exists. Are you sure you want to replace it?" kind of prompt. That could be done.
Keeping an out of date plaintext allows the program to avoid implementing secure deletion. The file plain.txt is renamed to plain.txt.1 or whatever, and the user can deal with disposing of plain.txt.1.
Yeah, this is a risk. We've been asked to implement a secure wipe, but I've always felt it is better to use tools like shred. That said, some SSD drives cannot be securely wiped, anyway, even if you use a tool like that. File local file system security, it's better to use an encrypted volume. For storing files somewhere else, sending via email, etc. use of AES Crypt makes sense. I would not want to implement something where AES Crypt creates .1 files and such. Some people get confused by the very fact there is a .doc and .doc.aes. Creating a .doc.aes.1 would really cause confusion. Simplicity is important, I've learned. Paul
Patch for detecting that destination files cannot be written prior to asking for password. If any file exists, and can be opened for reading, then a simple message is issued for that file and the operation is canceled, e.g: Output file C:\foo.txt exists already If a file exists, but cannot be opened for reading then the reason is added to the error message. For example: Output file C:\foo.txt exists already: Access is denied. diff -urp AESCrypt_source_v309-ORIG/AESCrypt/AESCryptWorkerThreads.cpp AESCrypt_source_v309/AESCrypt/AESCryptWorkerThreads.cpp --- AESCrypt_source_v309-ORIG/AESCrypt/AESCryptWorkerThreads.cpp 2013-03-09 23:13:54.000000000 -0800 +++ AESCrypt_source_v309/AESCrypt/AESCryptWorkerThreads.cpp 2013-09-06 02:16:14.849193800 -0700 @@ -104,23 +104,17 @@ void AESCryptWorkerThreads::ProcessFiles { PasswdDialog dlg; - // Prompt the user for a password - if (dlg.DoModal(::GetActiveWindow(), (encrypt ? 1 : 0)) == IDOK) - { - if (StartThread(file_list, - dlg.passwd, - encrypt) == false) - { - // We were unable to start a thread, so we must clean up - // the file list. - delete file_list; - } - } - else - { - // The user canceled the operation, so delete the file list - delete file_list; - } + if (CheckOverwriteFiles(file_list, encrypt) && // files are not in the way + dlg.DoModal(::GetActiveWindow(), (encrypt ? 1 : 0)) == IDOK && // prompt for password + StartThread(file_list, dlg.passwd, encrypt)) // start thread + { + // Thread started successfully and now owns file_list + return; + } + + // The operation did not proceed so ownership of the file + // list did not pass to the thread; we must delete it. + delete file_list; } /* @@ -283,6 +277,32 @@ DWORD WINAPI ThreadInit(LPVOID lpParamet } /* + * CheckOverwriteFiles + * + * Returns false if any of the destination files of the given + * file list already exist or cannot be used. + */ +bool AESCryptWorkerThreads::CheckOverwriteFiles( + StringList *file_list, + bool encrypt) +{ + for (StringListIter i = file_list->begin(); i != file_list->end(); i++) { + const String &name = *i; + String dest = encrypt ? name + _T(".aes") : name.substr(0, name.length() - 4); + BufferedFile check_file; + DWORD result_code = check_file.OpenFile(dest.c_str(), false, OPEN_EXISTING); + + if (result_code != ERROR_FILE_NOT_FOUND) { + ::ReportError( _T("Output file ") + dest + _T(" exists already"), + result_code); + return false; + } + } + + return true; +} + +/* * EncryptFiles * * This function is called by the worker thread to encrypt a list of files. diff -urp AESCrypt_source_v309-ORIG/AESCrypt/AESCryptWorkerThreads.h AESCrypt_source_v309/AESCrypt/AESCryptWorkerThreads.h --- AESCrypt_source_v309-ORIG/AESCrypt/AESCryptWorkerThreads.h 2013-03-09 23:13:54.000000000 -0800 +++ AESCrypt_source_v309/AESCrypt/AESCryptWorkerThreads.h 2013-09-06 01:43:02.101147000 -0700 @@ -27,6 +27,9 @@ class AESCryptWorkerThreads inline void DoMessageLoop(); + bool CheckOverwriteFiles( StringList *file_list, + bool encrypt); + void EncryptFiles( StringList *file_list, TCHAR *passwd); diff -urp AESCrypt_source_v309-ORIG/AESCrypt/stdafx.h AESCrypt_source_v309/AESCrypt/stdafx.h --- AESCrypt_source_v309-ORIG/AESCrypt/stdafx.h 2013-03-09 23:13:54.000000000 -0800 +++ AESCrypt_source_v309/AESCrypt/stdafx.h 2013-09-06 01:26:21.891136400 -0700 @@ -41,7 +41,9 @@ // STL #include <list> -typedef std::list< std::basic_string<TCHAR> > StringList; +typedef std::basic_string<TCHAR> String; +typedef std::list< String > StringList; +typedef std::list< String >::iterator StringListIter; // Win32 #include <commctrl.h>
OK... I'll add this to the to-do list :-) But, I'm not sure when I'll have it done. It will likely not be until sometime over the next 3 months. Paul
-----Original Message----- From: aescrypt-bounces@lists.packetizer.com [mailto:aescrypt- bounces@lists.packetizer.com] On Behalf Of Kaz Kylheku Sent: Friday, September 06, 2013 5:35 AM To: aescrypt@lists.packetizer.com Subject: [aescrypt] PATCH: Detect that some destination files (plain or .aes) cannot be written prior to collecting password.
Patch for detecting that destination files cannot be written prior to asking for password.
If any file exists, and can be opened for reading, then a simple message is issued for that file and the operation is canceled, e.g:
Output file C:\foo.txt exists already
If a file exists, but cannot be opened for reading then the reason is added to the error message. For example:
Output file C:\foo.txt exists already: Access is denied.
diff -urp AESCrypt_source_v309-ORIG/AESCrypt/AESCryptWorkerThreads.cpp AESCrypt_source_v309/AESCrypt/AESCryptWorkerThreads.cpp --- AESCrypt_source_v309-ORIG/AESCrypt/AESCryptWorkerThreads.cpp 2013-03- 09 23:13:54.000000000 -0800 +++ AESCrypt_source_v309/AESCrypt/AESCryptWorkerThreads.cpp 2013-09-06 02:16:14.849193800 -0700 @@ -104,23 +104,17 @@ void AESCryptWorkerThreads::ProcessFiles { PasswdDialog dlg;
- // Prompt the user for a password - if (dlg.DoModal(::GetActiveWindow(), (encrypt ? 1 : 0)) == IDOK) - { - if (StartThread(file_list, - dlg.passwd, - encrypt) == false) - { - // We were unable to start a thread, so we must clean up - // the file list. - delete file_list; - } - } - else - { - // The user canceled the operation, so delete the file list - delete file_list; - } + if (CheckOverwriteFiles(file_list, encrypt) && // files are not in the way + dlg.DoModal(::GetActiveWindow(), (encrypt ? 1 : 0)) == IDOK && // prompt for password + StartThread(file_list, dlg.passwd, encrypt)) // start thread + { + // Thread started successfully and now owns file_list + return; + } + + // The operation did not proceed so ownership of the file + // list did not pass to the thread; we must delete it. + delete file_list; }
/* @@ -283,6 +277,32 @@ DWORD WINAPI ThreadInit(LPVOID lpParamet }
/* + * CheckOverwriteFiles + * + * Returns false if any of the destination files of the given + * file list already exist or cannot be used. + */ +bool AESCryptWorkerThreads::CheckOverwriteFiles( + StringList *file_list, + bool encrypt) +{ + for (StringListIter i = file_list->begin(); i != file_list->end(); i++) { + const String &name = *i; + String dest = encrypt ? name + _T(".aes") : name.substr(0, name.length() - 4); + BufferedFile check_file; + DWORD result_code = check_file.OpenFile(dest.c_str(), false, OPEN_EXISTING); + + if (result_code != ERROR_FILE_NOT_FOUND) { + ::ReportError( _T("Output file ") + dest + _T(" exists already"), + result_code); + return false; + } + } + + return true; +} + +/* * EncryptFiles * * This function is called by the worker thread to encrypt a list of files. diff -urp AESCrypt_source_v309-ORIG/AESCrypt/AESCryptWorkerThreads.h AESCrypt_source_v309/AESCrypt/AESCryptWorkerThreads.h --- AESCrypt_source_v309-ORIG/AESCrypt/AESCryptWorkerThreads.h 2013-03-09 23:13:54.000000000 -0800 +++ AESCrypt_source_v309/AESCrypt/AESCryptWorkerThreads.h 2013-09-06 01:43:02.101147000 -0700 @@ -27,6 +27,9 @@ class AESCryptWorkerThreads
inline void DoMessageLoop();
+ bool CheckOverwriteFiles( StringList *file_list, + bool encrypt); + void EncryptFiles( StringList *file_list, TCHAR *passwd);
diff -urp AESCrypt_source_v309-ORIG/AESCrypt/stdafx.h AESCrypt_source_v309/AESCrypt/stdafx.h --- AESCrypt_source_v309-ORIG/AESCrypt/stdafx.h 2013-03-09 23:13:54.000000000 -0800 +++ AESCrypt_source_v309/AESCrypt/stdafx.h 2013-09-06 01:26:21.891136400 -0700 @@ -41,7 +41,9 @@
// STL #include <list> -typedef std::list< std::basic_string<TCHAR> > StringList; +typedef std::basic_string<TCHAR> String; +typedef std::list< String > StringList; +typedef std::list< String >::iterator StringListIter;
// Win32 #include <commctrl.h>
How about a way to verify one's knowledge of a key without doing the actual bulk decryption. Suppose I have an .aes file and I would like to answer the question "Does this file have the password that I think it has?" without actually decrypting the file. Furthermore, there could be an optional checkbox on this UI to actually do bulk-decrypt the file to verify its integrity, but without creating an output file. These tools could be used, for instance, by Bob to confirm to Alice that a file (which is to be processed by Bob at some later date) was correctly received. Cheers ...
How about a way to verify one's knowledge of a key without doing the actual bulk decryption.
AES Crypt already does that. The key/password decrypts a block of data that contains the "real" initialization vector and key used to do the bulk encryption. So, if you enter the wrong password 4 a 4GB file, it will not have to decrypt the entire 4GB file.
Suppose I have an .aes file and I would like to answer the question "Does this file have the password that I think it has?" without actually decrypting the file.
One has to do some decryption to get that answer, but it's fairly minimal. Some have argued against the approach, since one can test passwords faster. But, given that a strong password/key (i.e., one that's pretty random and long) would mean an attacker would have to try a very large number of passwords. A 256-bit key would mean there are 1.18 x 10^77 different keys to try.
Furthermore, there could be an optional checkbox on this UI to actually do bulk-decrypt the file to verify its integrity, but without creating an output file.
More options = more complexity and people get confused. A much easier way to see if a file is valid or not is to do an SHA-1 or SHA-256 hash over the file. I do precisely that when I archive files in cloud storage. I encrypt files, record the hash (before and after encryption), and then archive the file. When I pull the file from storage, I can verify the hash is what I had recorded in my local database. Now, that's a little more complex. But, you could do the same thing. Just produce hashes of encrypted files. Here are some SHA-1 tools to do that: http://www.packetizer.com/security/sha1/ It would also be possible to store the hash in the header of the .aes file. There is a TAG/VALUE section that is intended for storing metadata about the file. An SHA-1 hash value over the file (excluding the TAG/VALUE data) would be interesting. It could be inserted even after the encryption is done. But, I would not put that in AES Crypt. AES Crypt has to work in streaming mode where data comes in, is encrypted, and ciphertext goes out. But, one could introduce an "aes_integrity" utility to insert hashes. Or, just store the values somewhere. For example, have a file called "foo.txt.aes" and one called "foo.txt.sha1.txt" that contains the hash string.
These tools could be used, for instance, by Bob to confirm to Alice that a file (which is to be processed by Bob at some later date) was correctly received.
That really would require either a hash computation or decrypting the file. A problem with hashes for this case is that you don't know if the hash data was manipulated in transit. One solution might be to encrypt the hash file (foo.txt.sha1.txt) and send that, too. Then Bob could decrypt the hash file quickly (since it's very short) and then compute a hash over the encrypted data file see that it matches. Some of these things you want to do are interesting, but can easily be done with scripts at the Linux shell prompt. Adding this directly into AES Crypt just makes the program heavy. It's good to keep it simple and focused. Paul
On 05.09.2013 21:03, Paul E. Jones wrote:
How about a way to verify one's knowledge of a key without doing the actual bulk decryption.
AES Crypt already does that. The key/password decrypts a block of data that contains the "real" initialization vector and key used to do the bulk encryption. So, if you enter the wrong password 4 a 4GB file, it will not have to decrypt the entire 4GB file.
Suppose I have an .aes file and I would like to answer the question "Does this file have the password that I think it has?" without actually decrypting the file.
One has to do some decryption to get that answer, but it's fairly minimal.
I basically got this all working in a satisfactory way; just some minor tweaks are needed. Now when you right click in Windows Explorer on one or more .aes files, you get two AES menu items: AES Decrypt and AES Check. (For non-crypted files, you get just AES Encrypt, as usual.) AES Decrypt is the same as before. AES Check brings up nearly the same password dialog as decrypt, except that the title is different and there is an extra checkbox to optionally verify the integrity of the file. If you checkbox the verification option, then the program goes through the full decrypt and HMAC verification. In both cases, failure invokes the existing logic and its error messages. Success brings up confirmation messageboxes informing the user that the password is okay, or that the file appears to be is unaltered. What I have left to do is to automatically dismiss the progress bar dialog when verification is done. Right now, I get the success message box bubbling up, while the progress bar still continues moving for a fraction of a second in the background, and remains visible until the success message box is dismissed.
More options = more complexity and people get confused. A much easier way to see if a file is valid or not is to do an SHA-1 or SHA-256 hash over the file. I do precisely that when I archive files in cloud storage. I encrypt files, record the hash (before and after encryption), and then archive the file. When I pull the file from storage, I can verify the hash is what I had recorded in my local database.
Now, that's a little more complex. But, you could do the same thing. Just produce hashes of encrypted files. Here are some SHA-1 tools to do that: http://www.packetizer.com/security/sha1/
But there is already SHA-1 hashing inside AESCrypt; there is value and simplicity in being able to just use that to check the file. More tools, extraneous files (or file properties) and manual steps are going to be daunting for the average end user, comparing to having a simple, integrated way to do this.
Some of these things you want to do are interesting, but can easily be done with scripts at the Linux shell prompt.
This is obviously not easy for the average user who doesn't have a clue about Linux and shell scripting (and is on Windows anyway). The Windows Explorer integrated form of AESCrypt is very easy to use. Non-programmer type people can wrap their heads around it in the space of a 10 minute tutorial, and I think it is still that way with this check password/validate functionality. It can be easily explained as a "dry run" which just scans the file to check that it can be decrypted, as if the computer were doing it "mentally" without actually writing out the result to a file.
participants (2)
-
Kaz Kylheku
-
Paul E. Jones