4
$\begingroup$

I'm writting a tool to save files (to external drive, cloud,...), it can already crypt file content with AES/GCM/NOPADDING; and as I'm not an expert, I've read some documentation, and understand that I have to generate (for each file) a random IV, that I can store directly into the crypted data (prepend). This part is OK (I hope).

But now I want to "obfuscate" the filename. As I want that the resulting string is "secure" (so not use a easy rot13/caesar cipher, that can be hack), I've tried to use the same approach (base64 the crypted byte array). But if I'm doing this, my resulting filename will never be the same! Encrypt "test.jpg" can give "abc", but encrypt again the original string "test.jpg" will give another result like "drsdf"... as the IV is generated randomly each time. And so my backup tool can't compare "filename" to do its checks.

Is there a way to obfuscate in a secure way a string but giving always the same result?

Update

Ok, I continue with my questions / investigations. So I use AES/GCM for content encryption with unique random IV (for each file). As I understand, I can't really use IV for filename encryption (need to save the IV into the crypted filename, which is problematic).

So new question for filename encryption: What is better to do:

  • Use AES/GCM (or CBC) with the same IV for all filenames?
  • Or use ECB mode which does not require IV?

And do I need to use or not use the same secret KEY for file content and file name encryption (as I will use 2 different approachs)?

$\endgroup$
  • 1
    $\begingroup$ Encrypting any filename would probably result in an "encrypted filename" which would exceed the underlying filesystem's max filename length. This is, of course, if you use a filesystem to store data. Other means of data store, such as object storage like Ceph, may help leverage this issue. Edit: The actual way you would encrypt the filename is probably with some public key crypto scheme. $\endgroup$ – Dreadlockyx Jan 26 '17 at 23:35
5
$\begingroup$

With a good encryption mechanism, knowing any number of plaintext-ciphertext pairs $\{(P_i,C_i)\}$ should reveal nothing about the plaintext corresponding to some extra ciphertext $C$, other than its length. In particular, given the knowledge that $P_1$ encrypts to $C_1$, an adversary should have no way to know whether some ciphertext $C$ also decrypts to $P_1$. This is a consequence of semantic security.

You may wish to weaken the security of the system to allow recognizing ciphertexts corresponding to a previously processed plaintext. That is, knowing plaintext-ciphertext pairs $\{(P_i,C_i)\}$ reveals no information about some ciphertext $C$ which is not one of the $C_i$.

This has dangerous implications that may not be obvious at first glance. In many cases, an adversary can convince the user to encrypt some plaintext (e.g. arrange for the user to download some files). So an adversary who wanted to decrypt some ciphertext file names could make guesses for the plaintext, arrange for the user to create files with this name, and compare the resulting ciphertext to verify these guesses.

Using non-repeated IVs in encryption algorithms avoids this by causing two plaintexts to never be encrypted to the same ciphertext, even if the plaintexts are equal, because the IVs will differ.

If you don't mind considerably weakening the confidentiality of file names, you can use a deterministic IV. Beware that you can't just use any old IV; for example, with CTR or GCM mode, repeating a counter value reveals the xor of the corresponding plaintext blocks, which leaks a lot of information. One method that is safe, other than enabling the encryption oracle guessing method I described earlier, is to make the IV a cryptographic hash of the file name. If the hash function is independent of the block cipher (which it typically is in practice, e.g. the SHA families are independent of AES) then the hash function can be idealized as a random oracle and so using a hash as the IV is equivalent to using a random IV as long as plaintexts are not repeated.

However, I wonder why you need to be able to recognize identical ciphertexts. Your backup tool has the symmetric key, so it can decipher the name of previously backed-up files. To avoid downloading ciphertexts from the server for local decryption, you would keep a local log of what has already been backed up, but backup programs usually have this anyway in some form.


Regarding your updates:

Use AES/GCM (or CBC) with the same IV for all filenames?

No. GCM requires a unique IV. Repeating the IV with GCM can not only break the confidentiality and integrity of the message, but can even leak information about the key. See How bad it is using the same IV twice with AES/GCM?

CBC with a repeated IV, in addition to making common prefixes obvious, leaks a little information about the plaintext. It also doesn't guarantee integrity.

Or use ECB mode which does not require IV?

No. ECB is not a proper encryption mode. It is implemented in some libraries for convenience but does not provide any security.

I can't really use IV for filename encryption (need to save the IV into the crypted filename, which is problematic)

You generally can't use the encrypted filename as a filename anyway, because the encrypted filename is longer than the original, even without counting the IV. Filesystems have forbidden characters, so you'd need some encoding scheme, which costs you bytes in the filename. Most filesystems have a limited filename length. The only case in which you can map plaintext filenames to encrypted filenames is if the source filesystem's filename length limit is sufficiently smaller than the target filename filesystems's length limit.

$\endgroup$
  • 2
    $\begingroup$ In practice, encrypting filenames in a deterministic way as you describe is probably futile in practice. Depending on the type of content being uploaded, 90%+ of filenames could be in a "well-known" format: README.md, DSC-xxxx.jpg, etc. Even if not, 90% of the rest could be brute-forced in a few hours by heuristic. $\endgroup$ – Stephen Touset Jan 27 '17 at 6:43
  • $\begingroup$ If OP is trying to determine if two files are identical, he can HMAC the contents before encryption to generate a uniquely-identifying content ID. $\endgroup$ – Stephen Touset Jan 27 '17 at 6:44
  • $\begingroup$ @StephenTouset What would be the point of the HMAC? The problem here is that the transformation from secret content to uploaded data is deterministic. Making it read-only doesn't solve this problem. $\endgroup$ – Gilles Jan 27 '17 at 9:37
  • $\begingroup$ OP indicated that he wanted to identify two identical files by filename. It's possible that's not exactly what they wanted to do, and in case not I wanted to offer an alternate approach. $\endgroup$ – Stephen Touset Jan 27 '17 at 19:05
  • 1
    $\begingroup$ @Alexxx So store the file names in a separate file. (Even without the IV, the encrypted file names can be longer than the source names, because the encrypted names can be arbitrary bytes, whereas there are byte values that can't appear in file names.) $\endgroup$ – Gilles Jan 28 '17 at 19:45
3
$\begingroup$

I think you can use deterministic encryption. For example use the same key and IV for every plaintext. This will result in the same ciphertext for the same plaintext.

However, this means that if you encrypt two files both named "README.txt" they will be encrypted to the same ciphertext and this will leak information to an attacker.

As Gilles has mentioned this might be acceptable for your system. I would also suggest that you try to add sufficient information to create a unique identifier for each file. On many filesystems it might be sufficient to use the full path. If they are sufficiently stable hard-drive attributes like in inodes could be used as well.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.