So I am using cryptopp to encrypt a file in a project and I am using AES-GCM. I have a 256bit key and a 128bit ivec and a 128bit tag that I use to encrypt files.

However, I want to know where the authentication tag is stored? I notice if I specify a tag size of 0 then the encrypted file size is the same number of bytes as the original file.

Is the authentication tag simply appended to the end of the file?

  • $\begingroup$ are you sure you have a 128-bit init vector? $\endgroup$ Commented Apr 26, 2015 at 6:33
  • $\begingroup$ Yes, why do you ask? $\endgroup$
    – Mo Beigi
    Commented Apr 26, 2015 at 6:33
  • 2
    $\begingroup$ because it is generally 96-bits, allowing 128-bits can cause nonce overlap since there is no independent block counter $\endgroup$ Commented Apr 26, 2015 at 6:34
  • $\begingroup$ @RichieFrame this application will be encrypting a large amount of files. Each file is encrypted using a master key + a randomly generated header iv for each file. Its more complicated than that but I assumed a 128bit iv would be fine in this case as I would also encrypt a file if its file size was under a specific size as to not encrypt too many bytes using the same ivec. $\endgroup$
    – Mo Beigi
    Commented Apr 26, 2015 at 6:39
  • 3
    $\begingroup$ The GCM specification from NIST specifies the 96 bit nonce as default on 8.2.1 of the document. GCM is required to do additional calculations for differently sized IV's. $\endgroup$
    – Maarten Bodewes
    Commented Apr 26, 2015 at 11:27

2 Answers 2


The authentication tag is defined as an output parameter in GCM (see section 7, step 7 of NIST SP 800-38D). In all the API's I've encountered it's appended to the ciphertext. Where it is actually placed is up to the protocol designer. The protocol designer may well consider the place behind the ciphertext as ad hoc default though. The name "tag" of course kind of indicates that it should be tagged to the ciphertext and that may well mean direct concatenation.

The tag is often considered part of the ciphertext within an API. This means that the API is less flexible, and that it requires the buffering of the ciphertext (up to the size of the tag value) as the decryption routine otherwise doesn't know where the ciphertext ends and the authentication tag starts. This means in turn that the online property of the counter mode encryption is damaged.

So in generally it is better to treat the authentication tag as separate parameter as API designer, and leave the location of the authentication tag up to the protocol designer. The protocol designer may well choose to prefix the ciphertext with a length component, which would render the buffering unnecessary.

In your case it doesn't help to directly look at the GCM specification, you need the protocol or API specifications. I would suggest to look for it at the end of the ciphertext if the location hasn't been strictly defined. The tag size should be a valid, predefined parameter value.

In RFC 5116: An Interface and Algorithms for Authenticated Encryption the authentication tag is explicitly placed at the end of the ciphertext for GCM mode encryption. This is due to the following requirement in section 2.1:

There is a single output:

  • A ciphertext C, which is at least as long as the plaintext or
  • an indication that the requested encryption operation could not be performed.

and further explained by section 5.1:

The AEAD_AES_128_GCM ciphertext is formed by appending the authentication tag provided as an output to the GCM encryption operation to the ciphertext that is output by that operation.

This RFC is - for instance - used by the TLS specifications. Note that the size of the ciphertext is made explicit in those specifications, which means it should be easy to separate the tag from the actual ciphertext.

  • 3
    $\begingroup$ I've just written a proposal for an international API specification that doesn't directly "tag the tag" to the end of the ciphertext. The size of the ciphertext was usually known in advance anyway, so the required buffering during decryption just added unnecessary overhead on an already constrained system (and it messes up the symmetry with the encryption functionality, as that doesn't need to buffer). $\endgroup$
    – Maarten Bodewes
    Commented Apr 26, 2015 at 11:35

Insofar as you're using the Web Crypto API, this is specified in aes-gcm-operations: (C = ciphertext, T = authTag.)

Let ciphertext be equal to C | T, where '|' denotes concatenation.

So, to get the ciphertext and authTag seperately you have to slice the output of the encryption operation which is a byte array, or arrayBuffer. The index to split at depends on the authTag length.

JavaScript would look like:

let authTagLengthBytes = tagLength / 8;
let authTagBytes = cipherText.slice(cipherText.byteLength - authTagLengthBytes,cipherText.byteLength);
let authTag = new TextDecoder().decode(uint8array);

Your Answer

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

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