0

I'm working on a secure file manager program and I have a problem.

Well, suppose the user selects and encrypts a file, such as Test.mp3, from an external disk, and the Test.lock file is created on the disk. Now if the user wants to decrypt the Test.lock file, a Test.mp3 file is reset in disk which is dangerous, and we do not want the Test.mp3 file to be remain in disk, the first solution is to decrypt the test.mp3 in memory , But this idea works for small files, now my problem is that when the files are large, I can not keep all of them in memory, is there a way I can run Test.mp3 without Writing it to disk?

I mean, the .mp3 extension is a hypothesis, it could be any other extension. Encryption algorithm, it does not matter, I am looking for an idea, can anyone help me?

ɐsɹǝʌ ǝɔıʌ
  • 4,440
  • 3
  • 35
  • 56
Jack
  • 11
  • 1
  • Why do you say that saving the decrypted file to disk it's dangerous? Anyway, If you don't want to save the file to disk you can always create a temporary file and delete it once used. – ɐsɹǝʌ ǝɔıʌ Sep 15 '20 at 09:24
  • Well, if we use temp, it is possible to keep the file on disk – Jack Sep 15 '20 at 09:33
  • Then you have no choice. You'll have to spend your memory if you don't want to write to disk. And to be honest, this approach looks like more dangerous to me, especially when dealing with large files. What will do your program when you ran out of memory? Will die. – ɐsɹǝʌ ǝɔıʌ Sep 15 '20 at 09:55

1 Answers1

4

What you're looking for is on-the-fly decryption (and encryption if the user wants to modify the file too). On the one hand, most encryption in .NET is implemented through CryptoStream which is hardcoded to return false for CanSeek, on the other hand, seeking through an encrypted file (that is, jumping to a block immediately without decrypting the previous block) is possible if you use block cipher that supports random access decryption, you can have for example 7 GB of an encrypted video file and only decrypt the few bytes you need once at a time to allow user immediately playing, even jumping around the videos without decrypting the whole content. No large RAM or temporary files needed.

The problem is, while it's comparably trivial to allow seeking on your custom derivation of CryptoStream, the resulting stream is only readable by your app. You probably could set-up a decrypt-recognize file type-play/display file flow in your own app, but you'd have to support every filetype out there.

Instead, apps like VeraCrypt, Cryptomator, and BitLocker create a virtual drive to intercept calls like "give me byte 7-13 of file A.MP3" to translate into a decryption call and return the appropriate decrypted bytes (and vice versa for writes). You're no longer hobbled with supporting every file type, it's compatible with whatever user's 3rd party app to handle them like a regular file on a real drive. Doing this requires writing low-level drivers that can't be done on C#.

If you're wondering why bother creating an entire virtual drive when seemingly capturing each file into its own container is enough, modification to the file might leave portions of deleted or old blocks in the file system, this can be used by adversaries to attack the encryption. So you can't use your "Test.lock" paradigm in your app. Instead, it will be a mounted virtual drive/directory. The combination of cryptographic gotchas (since you're no longer using built-in libraries), the difficulty of implementing the low-level drivers, and the existence of built-in BitLocker, free & audited VeraCrypt means the chance for a yet-another encryption solution to succeed is low.

Martheen
  • 5,198
  • 4
  • 32
  • 55
  • Thanks for your answer, I had 2 questions, suppose I created a virtual driver and whenever a user wants to decrypt a file, the decrypted file is inserted into the virtual drive and executed. 1. How safe do you think this method is? 2. What is the difference between this method and On fly encryption method? – Jack Sep 16 '20 at 06:54
  • How are you planning to "insert" the file to the virtual drive? If you're going to decrypt the entire file first, then the user must wait for the long decryption process, and if this virtual drive is backed by a file, it's no different to decrypting to a temporary file (with all the security risk), while if it's backed by RAM, it still run afoul of the problem on dealing with large files – Martheen Sep 16 '20 at 08:06
  • If instead, you're planning the virtual drive to intercept the io call and translate it to encryption and decryption calls to the encrypted file, then it's just on the fly encryption to a file container I mentioned in my last paragraph. You also lost the benefit of creating an entire virtual drive, where you can have a program running inside your container with reference to multiple files still working correctly, music player/image viewer handling an album etc – Martheen Sep 16 '20 at 08:11
  • Last question, is there an API or framework or tutorial that i can implement on the fly encryption? – Jack Sep 16 '20 at 08:36
  • Making a seekable AES stream is easy, just a couple of lines https://stackoverflow.com/a/38974483/529282 there's also a ready to use file system library callable from .NET https://github.com/dokan-dev/dokany But whether they're actually safe, stable, and even made sense when Veracrypt exist (seriously, try it and ask yourself why would anyone want to use different app when it's so stable, simple and versatile) is the million dollar question. Auditing your code for security issues isn't easy nor cheap – Martheen Sep 16 '20 at 09:52