encrypt = async (key, plaintext) => {
  const iv = generateIv()

  // this result is the concatenation of Array Buffers [ciphertext, auth tag]
  const ciphertextArrayBuffer = await windowOrSelfObject().crypto.subtle.encrypt(
    getCiphertextParams(iv),
    key,
    plaintext
  )

  return appendBuffer(ciphertextArrayBuffer, iv)
}
@param {CryptoKey} key
@param {ArrayBuffer} plaintext
@returns {ArrayBuffer} encrypted Array Buffer

    encrypted is a concatentation of Array Buffers [ciphertext, auth tag, IV]

    The Authentication Tag is a hash of the plaintext to ensure the same data that
    is ecncrypted is the resulting data when decrypted. Note that the browser crypto
    library's result is the concatenation of Array Buffers [ciphertext, auth tag]

    The IV is a random intialization vector that prevents an attacker
    from determining a user's key. It can be exposed alongside the ciphertext safely.