Search code examples
javascriptencryptionbrowserwebcrypto-apisubtlecrypto

Obtaining the auth tag of a AES-GCM cipher in Web Crypto API


The Node.js crypto module provides a cipher.getAuthTag() implementation that returns a Buffer which contains the authentication tag after the data has been successfully encrypted.

The SubtleCrypto.encrypt() Web Crypto API method supports the AES-GCM encryption algorithm, but has no documentation on how to retrieve the authentication tag like in Node.js. Is this possible with the Web Crypto API? If so, how?


Solution

  • After some extensive internet research, I discovered that the Web Crypto encryption method appends the auth tag to the resulting ciphertext. By default, its length is 16 bytes, and can be extracted from the payload with array manipulation:

    const nonce = crypto.getRandomValues(new Uint8Array(12));
    const aes_key = await crypto.subtle.generateKey(
        {
            name: 'AES-GCM',
            length: 256,
        },
        true,
        ['encrypt', 'decrypt']
    );
    const encrypted = await crypto.subtle.encrypt(
        {
            name: 'AES-GCM',
            iv: nonce,
        },
        aes_key,
        new Uint8Array() //plaintext to be encrypted
    );
    
    const [value, auth_tag] = [
        encrypted.slice(0, encrypted.byteLength - 16),
        encrypted.slice(encrypted.byteLength - 16),
    ];
    //value will be ArrayBuffer of ciphertext
    //auth_tag will be ArrayBuffer of the authentication tag