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); }