1

So I need to encrypt a file server-side for transport from server to client and storage on client-side. I'm quite confused as to what I have to watch out for, as it seems like it's insanely easy to screw up really bad.

The files I need to encrypt

  • Are binary
  • Sometimes contain big areas of null bytes.
  • Are of medium size, usually < 1gb.
  • Usually start with the same or similar header, so plaintext will often be the same.
  • Dont need to be encrypted often, but decrypted often, as they will not be stored decrypted.
  • Should remain very secure for a long time.

What I thought I could do is to use AES-256 in OCB3 mode, as it seems to provide both authentication and encryption.

I'm however not very sure about how I would go about generating a suitable key from a password. Is using a simple hash function like SHA-256 secure?

I'm assuming I'll have to store the IV along with the file. Is that correct?

Would AES-256 in OCB3 mode be suitable for this sort of task or is there a better way of doing this?

By the way, I am aware that it's quite easy to read the decrypted file from memory when it's decrypted at client-side, but I'm afraid there's not much I can do about it.

Edit: Both server and client programs are written in c++. I also want to be able to encrypt and decrypt the files just in memory at runtime, so a lot of file encryption tools don't really fit the task.

thebear8
  • 123
  • 5

1 Answers1

4

I'm however not very sure about how I would go about generating a suitable key from a password. Is using a simple hash function like SHA-256 secure?

No, you'd generally use a Password Based Key Derivation Function such as a secure version of Argon2. But preferably, you'd not use a password at all. It is only one factor that's required and passwords generally do not contain enough entropy for long term storage.

One trick is to use a public key for hybrid encryption, and store the private key on a separate device that is only connected when the file needs to be decrypted. That private key in turn can be encrypted.

If you use a password, I'd use a password manager with a very large password.

I'm assuming I'll have to store the IV along with the file. Is that correct?

Not necessarily. The input of a PBKDF always contains a salt value to protect against rainbow tables. From the password and salt (as well as the work factor) the output keying material can be calculated. It is possible to retrieve both a key from the output bits and the IV from other output bits.

Of course, now you'd have to store the salt value.

Full file names are also unique and could be used for a mode of operation by hashing the filename. However, that means that the file cannot be copied to another location, so generally we would try and avoid such brittle constructions.

There is of course nothing particularly wrong by storing a (random) IV, as long as it is unique with a high probability.

Would AES-256 in OCB3 mode be suitable for this sort of task or is there a better way of doing this?

It's not better or worse than any other AEAD cipher I suppose.

By the way, I am aware that it's quite easy to read the decrypted file from memory when it's decrypted at client-side, but I'm afraid there's not much I can do about it.

Well, you should harden your clients to the best of your ability. But yeah, in the end you need to access the data, and it is too large to fit into any kind of secure enclave in all likelihood.

Edit: Both server and client programs are written in c++. I also want to be able to encrypt and decrypt the files just in memory at runtime, so a lot of file encryption tools don't really fit the task.

Tools: possibly not. Higher level encryption libraries are however certainly available, and libsodium has already been mentioned.

Maarten Bodewes
  • 96,351
  • 14
  • 169
  • 323