public byte[] Decrypt(byte[] password, byte[] aead)
        {
            byte[] derivedKey = DeriveKey(password);
            byte[] aesKey     = new byte[32];
            byte[] hmacKey    = new byte[32];
            Buffer.BlockCopy(derivedKey, 0, aesKey, 0, aesKey.Length);
            Buffer.BlockCopy(derivedKey, aesKey.Length, hmacKey, 0, hmacKey.Length);

            byte[] version = new byte[1];
            Buffer.BlockCopy(aead, 0, version, 0, version.Length);

            byte[] iv = new byte[16];
            Buffer.BlockCopy(aead, version.Length, iv, 0, iv.Length);

            byte[] hmac = new byte[32];
            Buffer.BlockCopy(aead, aead.Length - hmac.Length, hmac, 0, hmac.Length);

            byte[] ciphertext = new byte[aead.Length - (version.Length + iv.Length + hmac.Length)];
            Buffer.BlockCopy(aead, version.Length + iv.Length, ciphertext, 0, ciphertext.Length);

            byte[] hmacRef = new byte[version.Length + iv.Length + ciphertext.Length];
            Buffer.BlockCopy(aead, 0, hmacRef, 0, hmacRef.Length);

            // authenticate
            byte[] computedHmac = new HMACSHA256(hmacKey).ComputeHash(hmacRef);
            if (!computedHmac.SequenceEqual(hmac))
            {
                string message = "Authentication mismatch!";
                if (Debug.isDebugBuild)
                {
                    message = string.Format("Authentication mismatch! Expected:{0} | Given:{1}", hmac, computedHmac);
                }
                throw new CryptographicException(message);
            }

            // decrypt
            var aes = PrepareAes(aesKey);

            aes.IV = iv;
            var data = aes.CreateDecryptor().TransformFinalBlock(ciphertext, 0, ciphertext.Length);

            return(data);
        }