public static DecryptInfo Decrypt(Stream input, Stream output, string password, Action <double> progress = null, Func <bool> isCanceled = null)
        {
            var decryptInternalParameter = new DecryptInternalParameter
            {
                Progress   = progress,
                IsCanceled = isCanceled,
            };

            return(DecryptInternal(input, output, null, password, decryptInternalParameter));
        }
        public static DecryptInfo Decrypt(string inputPath, string outputPath, string password, Action <double> progress = null, Func <bool> isCanceled = null)
        {
            var decryptInternalParameter = new DecryptInternalParameter
            {
                Progress   = progress,
                IsCanceled = isCanceled,
            };

            using (var input = File.OpenRead(inputPath))
                using (var output = File.Open(outputPath, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite))
                    return(DecryptInternal(input, output, null, password, decryptInternalParameter));
        }
        internal static DecryptInfo DecryptInternal(Stream input, Stream output, byte[] secret, string password, DecryptInternalParameter parameter)
        {
            if (!RawFileAccessor.Verify(input))
            {
                throw new CryptographicException("File signature is wrong");
            }

            var fileCargo = RawFileAccessor.ReadMeta(input);

            if (password != null)
            {
                secret = Hasher.CreateAesKeyFromPassword(password, fileCargo.PasswordDerivationSettings.Salt, fileCargo.PasswordDerivationSettings.Iterations);
            }

            if (parameter?.EllipticCurveDeriveKeyAction != null)
            {
                secret = parameter?.EllipticCurveDeriveKeyAction(fileCargo.EllipticCurveEncryptionInformation);
            }

            SecretInformation decryptedSecretInfo = null;

            if (fileCargo.SecretInformationEncrypted != null)
            {
                var memoryStream = new MemoryStream();
                DecryptInternal(new MemoryStream(fileCargo.SecretInformationEncrypted), memoryStream, secret, null, null);
                decryptedSecretInfo = SecretInformation.FromProtoBufData(memoryStream.ToArray());
            }

            var iv   = RawFileAccessor.Read(input, RawFileAccessor.Field.InitializationVector);
            var hmac = RawFileAccessor.Read(input, RawFileAccessor.Field.Hmac);

            (byte[] hmac, byte[] iv)param = (hmac, iv);

            RawFileAccessor.SeekToMainData(input);
            DecryptRaw(input, output, secret, param, parameter?.Progress, parameter?.IsCanceled);

            return(new DecryptInfo
            {
                FileName = decryptedSecretInfo?.Filename,
            });
        }