1

I'm writing a program that can encrypt a file using AES cfb128 (using Openssl and C++).

The scenario of the program is this:

  • Person A visits computer, encrypts a file they make, takes away a key (on USB stick?)
  • Person B visits computer and is unable to decrypt encrypted file
  • Person A comes back and decrypts the file using their key

My question is I have an encryption key and initialization vector that I must set for the AES encryption. I plan on randomly generating numbers for one and using a hardware ID for the other. Also the person could choose to encrypt multiple files.

So how would I do this?
Can I make the encryption key the hardwareID and the init vector a sequence of random bits?

If the same hardwareID and init vector are used to encrypt multiple files per machine, is this unsecure given that an attacker will not have the init vector but may have the encryption key? Should the encryption key be the random bit instead and the hardware key be the init vector?

Or should both the encryption key and init vector be random and unknown to the attacker? And if so, is it secure to encrypt multiple files using the same 2 unknown keys?

Mo Beigi
  • 245
  • 1
  • 4
  • 9

1 Answers1

3

You can use your HardwareID as basis for the encryption key. If the ID provides enough entropy it'll work. However, if anyone can somehow obtain the ID (which might be quite easy to do) one can decrypt the file.

For CFB-Mode the IV must indeed be unpredictable (but need not be secret), so random is just fine, but DO NOT REUSE AN IV.

Encryption large amounts of data with the same key and different IVs is just fine and no problem at all.


However, I want to propose some improvements for the security level.

  1. Don't use CFB-Mode but EAX/CCM/GCM-Mode, as they are authenticated and hence you've authentication "for free" without any further worries.
  2. As replacement for the Hardware-ID based Key I'd suggest either storing the key (plain - not recommended) on the USB-Stick, or only use a password (+ scrypt) or store the key encrypted (AES-GCM+scrypt) on a stick.
  3. You might want to consider generating a key for each file you encrypt and storing this key (+IV) as a "header" for the encrypted file. The header would be decrypted using the secret key (from USB / from password / from USB+password)
SEJPM
  • 45,967
  • 7
  • 99
  • 205
  • The hardware ID is quite easy to find I suppose (via reverse engineering). This means an attacker could discover it. Should I add use a random key instead (and ditch the hardware ID) and store it securely on the USB stick?

    And I really like the suggestion in 3. So I simply randomly generate and add 128 bits (length of IV) to the start of each encrypted file. In the decryption process, I read this back into the program and use it (in combination with the key provided by the USB stick) to decrypt the file.

    However, if I use one of those authenticated modes, I don't require an Init vector?

    – Mo Beigi Apr 08 '15 at 16:31
  • Every mode (except ECB, which shouldn't be used) requires an IV. The authenticated modes require an IV as well. You can use the hardware-ID, but as doesn't add any security I'd recommend against it. Rather store the key on your usb-stick (encrypted+authenticated with AES-GCM and key derived via scrypt from your password). My proposal in 3 was to encrypt & authenticate the file using a key, generated only for this file and stored encrypted (along with the corresponding IV) in the header, for which you'd also need an IV. Hence you'd expand the file by ~64 bytes (2x 128bit IV + 256bit key) – SEJPM Apr 08 '15 at 17:16
  • I decided to change AES mode to GCM, the authentication is nice. Anyway, could I generate 1 secret key for 1 machine (hardware ID + random key) and 1 unique/random key as ivec for each file and append this ivec to the begging of each file and securely store the key on a USB stick. Now to decrypt, a user comes back to the machine, provides the secret key along and the program gets the plain text ivec from the header of each file and uses that to decrypt the file. Is there a better way to store the ivec than plain text or does it not matter? I don't quite understand your 3rd point yet. – Mo Beigi Apr 09 '15 at 08:34
  • An IV is not a key and hence doesn't need to be secret. Furthermore GCM "only" requires a unique IV. You can use the proposed construction of a random key safely for file encryption, as the entropy of the random key suffices for security. For decryption my idea is, that a user comes back to the machine, deciphers the master key on the usb-stick using his password, this key is used to decrypt the file's header, yielding the data key and the data iv, which is then used to decrypt the file. This might help you. – SEJPM Apr 09 '15 at 10:33
  • How would the master key be securely stored? And how would the file header be encrypted to that it can hide the secret key and iv for that file? And is this approach more secure than storing the IV as plain text in the header for each file and securely transferring the secret key (perhaps the user will use RSA to encrypt the key on their USB stick). I feel your approach is very clever and overall a better solution but is it that much more secure? – Mo Beigi Apr 09 '15 at 12:25
  • The approach I'm suggesting is technically not more secure (the whole thing with keys that decrypt keys,...) as you probability find the key via brute-force rises (from $2^{-255}$ to ~$2^{-253}$). But with this way you implement two-factor-authentication (you need stick + password) and are much more flexible, f.ex. you'd need to change the stored master key if password is changed (and not all everything). And if your master key gets compromised and you're sure that certain files haven't been touched you'd only need to re-encrypt the header. I'll set up a document on how to store things soon. – SEJPM Apr 09 '15 at 18:56
  • formulated this. Comment as usual if there are questions left. Note: this will only be online for one month. Make a copy if you want to use it. – SEJPM Apr 09 '15 at 19:16
  • Thanks this is very useful for learning! I'll work on this. Two questions, do I need Additional Authenticated Data mode to get the header_tag and what is the header_tag used for? My current code simply takes a TAG_SIZE but I don't see a way to actually get the tag (using GCM-AE as described here: http://www.cryptopp.com/wiki/GCM_Mode). Also you made a point about not encrypting more than 500 GiB with same IV, what happens if this occurs, does it reveal some information about the data? (This won't happen in my case so I am just curious). Thanks again! – Mo Beigi Apr 10 '15 at 06:11
  • Also I might make a new question if I run into issues as we're drifting away from the initial question I asked. – Mo Beigi Apr 10 '15 at 06:14
  • encrypting more than $2^{39}-256$ bytes with the same IV is forbidden by GCM specification. I assume that collision probility would be too high for larger amounts. I'm not sure about this, but I assume Crypto++ handels the whole tag thing automatically if you use filters. the header_tag authenticates the data_key and the data_iv (you can also auth. header_IV via associated data, second sample on the linked page) – SEJPM Apr 10 '15 at 09:04
  • Ah fair enough, if I simply encrypt the Data_Key and Data_IV the tag will be added by CryptoPP itself. So I can confirm integrity when decrypting the header. I think I won't use additional authenticated data as I don't really need it. Thanks again! – Mo Beigi Apr 10 '15 at 16:09