49
$\begingroup$

I am looking into using AES256-GCM for encrypting some database fields. I know that for AES256-CBC, I need to generate a new IV for each encrypt, but I can use the same key. The IV can be openly stored alongside the ciphertext (ie, it can be public).

I started to read about GCM, but I don't quite understand some things. On this Stackexchange Thread, it is stated that:

  • GCM does not need an IV supplied.
  • Associated Tag is not necessary, but may improve security (example they gave is using a database id)

But Wikipedia states about GCM:

GCM has been proven secure in the concrete security model.[13] It is secure when it is used with a block cipher mode of operation that is indistinguishable from a random permutation; however security depends on choosing a unique initialization vector for every encryption performed with the same key (see stream cipher attack).

  1. Which implies that the IV still needs to be randomly generated and supplied for each encrypt with GCM, so why does the user in the stackexchange answer post say that we are not required to provide the IV?

    Wikipedia also states:

    The authentication strength depends on the length of the authentication tag, as with all symmetric message authentication codes. However, the use of shorter authentication tags with GCM is discouraged. The bit-length of the tag, denoted t, is a security parameter. In general, it may be any one of the following five values: 128, 120, 112, 104, or 96.

  2. In OP's post in that stackexchange thread, OP uses tag = cipher.auth_tag. Is this by default 96? If so, is there a way to change it? Are there significant performance issues in using 128 than 96?

  3. Does both the Associated Tag (cipher.auth_data) and the Authentication Tag (cipher.auth_tag) need to be kept secret? Or can they be kept open like the IV?

  4. Finally, can someone explain further what is meant by the Associated Tag? The example in the answer that was given in OP's thread was that we can use a database id to ensure that the data belongs to a certain database user. Let's say that a user has the following database fields:

    User
    - primary_id
    - encrypted_email
    

    And we want to encrypt the User's email before insertion. With User primary_id==10 (modifying OP's ruby code):

    cipher = OpenSSL::Cipher::AES.new(128, :GCM)
    cipher.encrypt
    key = cipher.random_key
    iv = cipher.random_iv
    cipher.auth_data = "10"    # Using DB user's id!
    
    encrypted = cipher.update(data) + cipher.final
    tag = cipher.auth_tag
    

    I replaced cipher.auth_data with the database user's primary_id. Is this correct?

$\endgroup$
2
  • 2
    $\begingroup$ GCM absolutely does need an IV. The comment on that thread is that it doesn't need to be included as part of the auth_data. $\endgroup$ Jul 3, 2014 at 23:12
  • 4
    $\begingroup$ The auth_data is arbitrary contextual information (for instance, the database primary key of the encrypted message, or a username, or a string scoping the action to a specific "purpose") that must be provided verbatim upon decryption. It can be public, but it shouldn't be controllable by the entity providing ciphertexts to be decrypted. The auth_tag is the output of the authentication half of the cipher, and is what is used upon decryption to detect any changes to the key, ciphertext, IV, or auth data. It can be stored alongside the encrypted output. $\endgroup$ Jul 3, 2014 at 23:17

1 Answer 1

57
$\begingroup$

Before answering your questions: GCM is an authenticated encryption mode of operation, it is composed of two separate functions: one for encryption (AES-CTR) and one for authentication (GMAC). It receives as input:

  1. a Key
  2. a unique IV
  3. Data to be processed only with authentication (associated data)
  4. Data to be processed by encryption and authentication

It outputs:

  1. The encrypted data of input 4
  2. An authentication TAG

The authentication TAG is an input to the decryption, if someone tampered with your associated data or with your encrypted data, GCM decryption will notice this and will not output any data (or return an error and you should discard the received data without processing it)

Now:

Which implies that the IV still needs to be randomly generated and supplied for each encrypt with GCM, so why does the user in the StackExchange answer post say that we are not required to provide the IV?

GCM requires an IV, it is used both by AES-CTR and by AES-GMAC, so no matter what you are doing with GCM, you need to pass an IV. It is required to be unique not necessarily random. Usually, implementations take a 96-bit IV and this is the recommended way to use GCM according to NIST.

In OP's post in that StackExchange thread, OP uses tag = cipher.auth_tag. Is this by default 96? If so, is there a way to change it? Are there significant performance issues in using 128 than 96?

By default, the authentication tag is 128 bit. You should provide the authentication TAG to the receiver of your message, so in some applications make sense to use a smaller tag. Keep in mind that the smaller tag you have, the more collisions you might get. If bandwidth is not an issue, use 128.

See also the detailed section on auth_tag([ tag_len ] → string here

Does both the Associated Tag (cipher.auth_data) and the Authentication Tag (cipher.auth_tag) need to be kept secret? Or can they be kept open like the IV?

The associated data (incorrectly you wrote Associated Tag) is used for data to be publicly known. Examples are headers or destination address. So it's not required to be secret, but if need to encrypt everything, then set the associated data to "". The authentication Tag is not required to be secret and in fact, it must be provided to the receiver unencrypted (like the IV).

Finally, can someone explain further what is meant by the Associated Tag? The example in the answer that was given in OP's thread was that we can use a database id to ensure that the data belongs to a certain database user. Let's say that a user has the following database fields:

It looks like you confuse the authentication data and authentication tag. The authentication data (or associated data) is something that you want to protect with authentication (if somebody modifies it you will know) but don't need to be encrypted. As stated above this is usually the case for headers which must be read by intermediate routers that can't decrypt the encrypted message.

The authentication Tag will depend upon the data you encrypt and on the associated data. So in decryption, you will need to process also the associated data or you will fail.

In your example, which is not very clear to me, you authenticate the primary id and the email and you encrypt the email. If you store in your DB both the IV and the TAG then you can decrypt the email if needed. Without an authentication tag an attacker could copy the email of user1 to the email of user2, if he also copies the IVs, then when you will lookup for the email of user2 you will successfully decrypt the email of user1 without noticing anything.

Instead, if you also use a TAG and process as associated data the id of the corresponding user, then an attacker could not do the previous attack, because in decryption will we notice the associated data wasn't the one used in encryption and the operation will fail (you will know someone tampered with user2 data).

$\endgroup$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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